Skip to content

Commit

Permalink
ae.utils.math.mixed_radix: Refactor out visitor
Browse files Browse the repository at this point in the history
  • Loading branch information
CyberShadow committed Jan 21, 2024
1 parent 41eb084 commit 0e8ca0d
Showing 1 changed file with 27 additions and 33 deletions.
60 changes: 27 additions & 33 deletions utils/math/mixed_radix.d
Original file line number Diff line number Diff line change
Expand Up @@ -192,71 +192,65 @@ template SerializationCoder(alias Coder, S)
private alias I = typeof(Coder.Decoder.init.get(0));
private alias E = typeof(Coder.RetroEncoder.init.finish());

private struct Serializer
private mixin template Visitor(bool retro)
{
Coder.RetroEncoder encoder;

void put(T)(auto ref const T value)
void visit(T)(ref T value)
{
static if (is(T : I) && is(typeof(T.max) : I))
{
I max = T.max;
I card = max; card++;
assert(card > max, "Overflow");
encoder.put(value, card);
handleLeaf(value, card);
}
else
static if (is(T == struct))
foreach_reverse (const ref field; value.tupleof)
put(field);
static if (retro)
foreach_reverse (ref field; value.tupleof)
visit(field);
else
foreach (ref field; value.tupleof)
visit(field);
else
static if (is(T == Q[N], Q, size_t N))
foreach_reverse (ref item; value)
put(item);
static if (retro)
foreach_reverse (ref item; value)
visit(item);
else
foreach (ref item; value)
visit(item);
else
static assert(false, "Don't know how to serialize " ~ T.stringof);
static assert(false, "Don't know what to do with " ~ T.stringof);
}
}

private struct Serializer
{
Coder.RetroEncoder encoder;
void handleLeaf(I value, I card) { encoder.put(value, card); }
mixin Visitor!true;
}

E serialize()(auto ref const S s)
{
Serializer serializer;
serializer.put(s);
serializer.visit(s);
return serializer.encoder.finish();
} ///

private struct Deserializer
{
Coder.Decoder decoder;

void get(T)(ref T value)
{
static if (is(T : I) && is(typeof(T.max) : I))
{
I max = T.max;
I card = max; card++;
assert(card > max, "Overflow");
value = cast(T)decoder.get(card);
}
else
static if (is(T == struct))
foreach (ref field; value.tupleof)
get(field);
else
static if (is(T == Q[N], Q, size_t N))
foreach (ref item; value)
get(item);
else
static assert(false, "Don't know how to deserialize " ~ T.stringof);
}
void handleLeaf(T)(ref T value, I card) { value = cast(T)decoder.get(card); }
mixin Visitor!false;
}

S deserialize(E encoded)
{
Deserializer deserializer;
deserializer.decoder = Coder.Decoder(encoded);
S result;
deserializer.get(result);
deserializer.visit(result);
static if (__traits(hasMember, deserializer.decoder, "empty"))
assert(deserializer.decoder.empty);
return result;
Expand Down

0 comments on commit 0e8ca0d

Please sign in to comment.