1 module cerealed.traits;
2 
3 import cerealed.cereal;
4 import cerealed.cerealiser;
5 import cerealed.decerealiser;
6 
7 
8 void checkCereal(T)() {
9     ubyte b;
10     auto cereal = T.init;
11     cereal.grainUByte(b);
12     uint val;
13     cereal.grainBits(val, 3);
14     CerealType type = cereal.type;
15     // can't check grainClass because it calls grainClassImpl,
16     // which uses the template constraint isCereal
17     // Class class_;
18     // cereal.grainClass(class_);
19 }
20 
21 enum isCereal(T) = is(typeof(checkCereal!T));
22 
23 void checkCerealiser(T)() {
24     checkCereal!T;
25     static assert(T.type == CerealType.WriteBytes);
26 }
27 
28 enum isCerealiser(T) = is(typeof(checkCerealiser!T));
29 
30 void checkDecerealiser(T)() {
31     checkCereal!T;
32     static assert(T.type == CerealType.ReadBytes);
33     auto dec = T();
34     ulong bl = dec.bytesLeft;
35 }
36 
37 enum isDecerealiser(T) = is(typeof(checkDecerealiser!T));
38 
39 
40 bool hasFunc(T, string funcName)() {
41     if(!__ctfe) {
42         auto obj = T.init;
43         auto enc = Cerealiser();
44         mixin("obj." ~ funcName ~ "(enc);");
45         auto dec = Decerealiser();
46         mixin("obj." ~ funcName ~ "(dec);");
47     }
48     return true;
49 }
50 
51 enum hasAccept(T)   = hasFunc!(T, "accept");
52 enum hasPostBlit(T) = hasFunc!(T, "postBlit");
53 enum hasPreBlit(T)  = hasFunc!(T, "preBlit");
54 
55 unittest {
56     struct Accept {
57         void accept(C)(auto ref C cereal) if(isCereal!C) { }
58     }
59 
60     static assert(hasAccept!Accept);
61 }
62 
63 mixin template assertHas(T, string funcName) {
64     static assert(hasFunc!(T, funcName));
65 }
66 
67 mixin template assertHasPostBlit(T) { mixin assertHas!(T, "postBlit"); }
68 mixin template assertHasPreBlit(T)  { mixin assertHas!(T, "preBlit"); }
69 mixin template assertHasAccept(T)   { mixin assertHas!(T, "accept"); }
70 
71 private class Class { ubyte ub; }