1 module tagion.tools.dartutil.dartindex;
2 
3 import std.format;
4 import tagion.basic.Types : Buffer;
5 import tagion.crypto.SecureInterfaceNet : HashNet;
6 import tagion.dart.DARTBasic : DARTIndex, dartKey;
7 import tagion.hibon.Document;
8 import tagion.tools.Basic;
9 import tagion.tools.toolsexception;
10 
11 DARTIndex dartIndexDecode(const(HashNet) net, const(char[]) str) {
12     import tagion.hibon.HiBONtoText;
13     import misc = tagion.utils.Miscellaneous;
14     import std.base64;
15     import std.algorithm;
16     import std.array : split;
17     import std.traits;
18     import tagion.hibon.Document : mut;
19     import tagion.hibon.HiBONBase;
20     import tagion.hibon.HiBONFile : fread;
21     import tagion.hibon.HiBONJSON : NotSupported, typeMap;
22 
23     verbose("dart-index %s", str);
24 
25     if (isBase64Prefix(str)) {
26         return DARTIndex(Base64URL.decode(str[1 .. $]).idup);
27     }
28     else if (isHexPrefix(str)) {
29         return DARTIndex(misc.decode(str[hex_prefix.length .. $]));
30     }
31     else if (str.canFind(":")) {
32 
33         const list = str.split(":");
34         const name = list[0];
35         if (list.length == 2) {
36             return net.dartKey(name, list[1].idup);
37         }
38     case_type:
39         switch (list[1]) {
40             static foreach (E; EnumMembers!Type) {
41                 {
42                     enum type_name = typeMap[E];
43                     static if (type_name != NotSupported) {
44                     case type_name:
45                         verbose("Htype %s -> %s", type_name, E);
46                         static if (E == Type.BINARY) {
47                             Buffer buf = list[2].decode;
48                             verbose("Dtype %s name=%s value=%(%02x%)", Buffer.stringof, name, buf);
49                             return net.dartKey(name, buf);
50                         }
51                         else static if (E == Type.DOCUMENT) {
52                             const doc = list[2].fread;
53                             verbose("Dtype %s name=%s value=\n%s", Document.stringof, name, doc.toPretty);
54                             return net.dartKey(name, doc.mut);
55                         }
56                         else static if (E == Type.STRING) {
57                             verbose("Dtype %s name=%s value=%s", string.stringof, name, list[2]);
58                             return net.dartKey(name, list[2].idup);
59                         }
60                         else static if (E == Type.TIME) {
61                             import std.datetime;
62 
63                             const val = SysTime.fromISOExtString(list[2]).stdTime;
64                             verbose("Dtype %s name=%s value=%s", SysTime.stringof, name, val);
65                             return net.dartKey(name, val);
66                         }
67                         else {
68                             alias Value = ValueT!(false, void, void);
69                             alias T = Unqual!(Value.TypeT!E);
70                             import std.conv : to;
71 
72                             auto val = list[2].to!T;
73                             verbose("Dtype %s name=%s value=%s", T.stringof, name, val);
74                             return net.dartKey(name, val);
75                         }
76                         break case_type;
77                     }
78                 }
79             }
80             default:
81             check(0, format("DART search %s not supported expected name:Type:value or name:text", str));
82         }
83         verbose("Dtype %s name=%s value=%s", string.stringof, name, list[2]);
84 
85         return net.dartKey(name, list[1].idup);
86     }
87 
88     return DARTIndex(misc.decode(str));
89 }
90 
91 immutable(Buffer) binaryHash(const(HashNet) net, scope const(ubyte[]) h1, scope const(ubyte[]) h2)
92 in {
93     assert(h1.length is 0 || h1.length is net.hashSize,
94             format("h1 is not a valid hash (length=%d should be 0 or %d", h1.length, net.hashSize));
95     assert(h2.length is 0 || h2.length is net.hashSize,
96             format("h2 is not a valid hash (length=%d should be 0 or %d", h2.length, net.hashSize));
97 }
98 out (result) {
99     if (h1.length is 0) {
100         assert(h2 == result);
101     }
102     else if (h2.length is 0) {
103         assert(h1 == result);
104     }
105 }
106 do {
107     assert(h1.length is 0 || h1.length is net.hashSize,
108             format("h1 is not a valid hash (length=%d should be 0 or %d", h1.length, net.hashSize));
109     assert(h2.length is 0 || h2.length is net.hashSize,
110             format("h2 is not a valid hash (length=%d should be 0 or %d", h2.length, net.hashSize));
111     if (h1.length is 0) {
112         return h2.idup;
113     }
114     if (h2.length is 0) {
115         return h1.idup;
116     }
117     return net.rawCalcHash(h1 ~ h2);
118 }