Skip to content

Commit

Permalink
ae.utils.math.mixed_radix: Add SerializationCoder
Browse files Browse the repository at this point in the history
  • Loading branch information
CyberShadow committed Jan 21, 2024
1 parent 5c4beee commit 19e8995
Showing 1 changed file with 102 additions and 0 deletions.
102 changes: 102 additions & 0 deletions utils/math/mixed_radix.d
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,108 @@ unittest
}
}
}

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
{
Coder.RetroEncoder encoder;

void put(T)(auto ref const 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);
}
else
static if (is(T == struct))
foreach_reverse (const ref field; value.tupleof)
put(field);
else
static if (is(T == Q[N], Q, size_t N))
foreach_reverse (ref item; value)
put(item);
else
static assert(false, "Don't know how to serialize " ~ T.stringof);
}
}

E serialize()(auto ref const S s)
{
Serializer serializer;
serializer.put(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);
}
}

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

unittest
{
static struct WithMax(T, T max_)
{
T value;
alias value this;
enum T max = max_;
}

enum E { a, b, c }
alias D6 = WithMax!(uint, 6);

static struct S
{
ubyte a;
bool b;
E[3] e;
D6 d;
}

alias Coder = SerializationCoder!(MixedRadixCoder!(uint, ulong, true), S);
auto s = S(1, true, [E.a, E.b, E.c], D6(4));
assert(Coder.deserialize(Coder.serialize(s)) == s);
}

private struct MaybeDynamicArray(T, size_t size = -1)
{
static if (size == -1)
Expand Down

0 comments on commit 19e8995

Please sign in to comment.