On Thursday, 30 October 2025 at 16:40:54 UTC, Dennis wrote:
> On Thursday, 30 October 2025 at 13:02:16 UTC, Hipreme wrote:
> Redub uses a cache system in which the hash of an object becomes a key. This does not translate well to structs as they are "random" keys. (...)
So you have several use cases where the keys are not a small set known ahead of time, but constructed dynamically. Makes sense, though now I wonder why you would use JSON for your cache or filesystem when performance is such a concern. Or when it's not a concern, why std.json doesn't suffice.
> There is another case in which the dynamic type API is kinda important, which is mostly when you do union types, so one would still need a good representation of it:
You could define:
struct Input
{
string keyboard;
string gamepad;
string analog;
string axis;
}
And then check the length of those strings to see if they have a value.
Either way, it's still useful to have a fast JSON parser using dynamic objects, and using std.json's API makes it an easy upgrade.
The reasons for why std.json didn't suffice:
- It uses a bunch of phobos dependencies which I can't use since I target multiple platforms with Hipreme Engine
- Redub started using hipjson because I found out that it was going way faster than std.json even though that meant I would use std.conv.to or other phobos functions
- I made that project available because I found out it was the fastest implementation for dynamic JSON objects in D
- After that, I grew a little nerdy on that and then made up d-segmmented-hashmap which was my response in going even further
Right now, HipJSON just release v1.0.1 which also supports streaming API:
import hip.data.json;
import std.exception;
JSONValue myJson;
JSONParseState state = JSONParseState.initialize(0);
enforce(JSONValue.parseStream(myJson, state, `{`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `"`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `h`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `e`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `l`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `l`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `o`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `"`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `:`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, ` `) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `"`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `w`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `o`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `r`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `l`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `d`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `"`) == JSONValue.IncompleteStream);
enforce(JSONValue.parseStream(myJson, state, `}`) != JSONValue.IncompleteStream);
import std.stdio;
writeln(myJson); //{"hello" : "world"}
What was more of a POC also wasn't that hard to get done, though I've got some bugfixes and even more performance improvement