1 module sbin.repr;
2 
3 import std.traits : Unqual;
4 
5 import sbin.serialize;
6 import sbin.deserialize;
7 
8 struct EmptyReprHandler { enum sbinReprHandler; }
9 
10 template isReprHandler(RH)
11 {
12     enum isReprHandler = is(RH == struct) && __traits(hasMember, RH, "sbinReprHandler");
13 }
14 
15 unittest
16 {
17     static struct Foo { }
18 
19     static assert(isReprHandler!EmptyReprHandler);
20     static assert(!isReprHandler!Foo);
21 }
22 
23 template hasRepr(RH, T) if (isReprHandler!RH)
24 {
25     static if (hasSerializeRepr!(RH, T))
26         enum hasRepr = hasDeserializeRepr!(RH, T, serializeRepr!(RH, T));
27     else
28         enum hasRepr = false;
29 }
30 
31 template hasSerializeRepr(RH, T)
32 { enum hasSerializeRepr = is(typeof(sbinSerialize!RH(RH.repr(T.init)))); }
33 
34 template hasDeserializeRepr(RH, T, Repr)
35 { enum hasDeserializeRepr = is(typeof(RH.fromRepr((ubyte[]).init.sbinDeserialize!(RH, Repr)())) == Unqual!T); }
36 
37 template serializeRepr(RH, T) if (hasSerializeRepr!(RH, T))
38 { alias serializeRepr = typeof(RH.repr(T.init)); }
39 
40 unittest
41 {
42     static class Foo {}
43     static struct Bar {}
44     static assert (!hasRepr!(EmptyReprHandler, int));
45     static assert (!hasRepr!(EmptyReprHandler, Foo));
46     static assert (!hasRepr!(EmptyReprHandler, Bar));
47 }
48 
49 unittest
50 {
51     import std.datetime : SysTime;
52 
53     static struct CRH
54     {
55         enum sbinReprHandler;
56 
57     static:
58 
59         long repr()(auto ref const SysTime st) { return st.stdTime; }
60         SysTime fromRepr()(auto ref const long v) { return SysTime(v); }
61     }
62 
63     static assert (isReprHandler!CRH);
64     static assert (!hasRepr!(EmptyReprHandler, SysTime));
65     static assert (hasSerializeRepr!(CRH, SysTime));
66     static assert (is(serializeRepr!(CRH, SysTime) == long));
67     static assert (hasDeserializeRepr!(CRH, SysTime, long));
68     static assert (hasRepr!(CRH, SysTime));
69 }