1 module tagion.betterC.mobile.DocumentWrapperApi;
2 
3 import tagion.betterC.hibon.Document;
4 import tagion.betterC.hibon.HiBON;
5 import tagion.betterC.mobile.Recycle;
6 import tagion.betterC.utils.Memory;
7 
8 // import tagion.basic.Recycle;
9 // import tagion.gossip.GossipNet;
10 // import tagion.betterC.wallet.Net : SecureNet;
11 // import tagion.wallet.KeyRecover;
12 
13 // import core.runtime : rt_init, rt_term;
14 // import core.stdc.stdlib;
15 import std.conv;
16 import std.stdint;
17 import std.string;
18 import tagion.basic.Types : Buffer;
19 
20 // import tagion.hibon.HiBONJSON;
21 
22 public Recycle!Document recyclerDoc;
23 
24 // static this() {
25 //     recyclerDoc = recyclerDoc.init;
26 // }
27 
28 // {
29 //     auto recyclerDoc = new reecycle!Document;
30 //     recycleDoc._active .... -> fine;
31 //     free(recyclerDoc);
32 //     recyclerDoc._active -> fail;
33 // }
34 
35 extern (C) {
36     enum BAD_RESULT = 0;
37 
38     string[] parse_string(const char* str, const uint len) {
39         string[] result;
40         return result;
41     }
42 
43     /// Functions called from d-lang through dart:ffi
44 
45     /// Creating Document by ubyte array
46     // export uint32_t create_test_doc()
47     // {
48     //     auto hibon = HiBON();
49     //     auto inner_hibon = HiBON();
50     //     auto arr_hibon = HiBON();
51     //     hibon["teststr"] = "test string";
52     //     hibon["testnum"] = 123;
53     //     hibon["testpk"] = cast(Buffer) [1,1,1,1];
54     //     const testarr = ["first", "second", "third"];
55     //     foreach(i, a; testarr){
56     //         arr_hibon[i] = a;
57     //     }
58     //     hibon["testarr"] = Document(arr_hibon);
59     //     inner_hibon["teststr"] = "inner test string";
60     //     hibon["inner"] = Document(inner_hibon);
61     //     auto doc = Document(hibon);
62     //     if (doc.isInorder())
63     //     {
64     //         auto docId = recyclerDoc.create(doc);
65     //         return docId;
66     //     }
67     //     return BAD_RESULT;
68     // }
69     /// Creating Document by ubyte array
70     export uint32_t create_doc(const uint8_t* data_ptr, const uint32_t len) {
71         // immutable(ubyte)[] data = cast(immutable(ubyte)[]) data_ptr[0 .. len];
72         ubyte[] data;
73         data.create(len);
74         for (size_t i = 0; i < len; i++) {
75             data[i] = data_ptr[i];
76         }
77         auto doc = Document(cast(immutable)(data));
78         if (doc.isInorder()) {
79             auto docId = recyclerDoc.create(doc);
80             return docId;
81         }
82         return BAD_RESULT;
83     }
84 
85     /// Deleting the specific Document
86     export void delete_doc_by_id(const uint32_t id) {
87         if (id !is BAD_RESULT) {
88             recyclerDoc.erase(id);
89         }
90     }
91 
92     // /// Getting the int value from Document by integer index
93     // export int32_t doc_get_int_by_id(const uint32_t doc_id, const uint32_t index)
94     // {
95     //     if (recyclerDoc(doc_id).hasMember(index))
96     //     {
97     //         return recyclerDoc(doc_id)[index].get;
98     //     }
99     //     return BAD_RESULT;
100     // }
101 
102     /// Getting the int value from Document by string key
103     export int32_t doc_get_int_by_key(const uint32_t doc_id, const char* key_str, const uint32_t len) {
104         // immutable key = cast(immutable)(key_str[0 .. len]);
105         char[] key;
106         key.create(len);
107         for (int i = 0; i < len; i++) {
108             key[i] = key_str[i];
109         }
110         if (recyclerDoc(doc_id).hasMember(cast(string)(key))) {
111             return recyclerDoc(doc_id)[cast(string) key].get!int;
112         }
113         return BAD_RESULT;
114     }
115     /// Getting the ulong value from Document by string key
116     export int64_t doc_get_ulong_by_key(const uint32_t doc_id, const char* key_str, const uint32_t len) {
117         char[] key;
118         key.create(len);
119         for (int i = 0; i < len; i++) {
120             key[i] = key_str[i];
121         }
122         if (recyclerDoc(doc_id).hasMember(cast(string)(key))) {
123             return recyclerDoc(doc_id)[cast(string) key].get!ulong;
124         }
125         return BAD_RESULT;
126     }
127     // /// Getting the string value from Document by index
128     // /// It uses UF-16 codding
129     // export const(char*) doc_get_str_by_id(const uint32_t doc_id, const uint32_t index)
130     // {
131     //     if (recyclerDoc(doc_id).hasMember(index))
132     //     {
133     //         string str = recyclerDoc(doc_id)[index].get!string;
134     //         return toStringz(str);
135     //     }
136     //     return null;
137     // }
138 
139     // /// getting the string value from Document by string key
140     // /// It uses UF-16 codding
141     export const(char*) doc_get_str_by_key(const uint32_t doc_id, const char* key_str, const uint32_t len) {
142         char[] key;
143         key.create(len);
144         for (int i = 0; i < len; i++) {
145             key[i] = key_str[i];
146         }
147         if (recyclerDoc(doc_id).hasMember(cast(string)(key))) {
148             string str = recyclerDoc(doc_id)[cast(string) key].get!string;
149             return str.ptr;
150         }
151         return null;
152     }
153 
154     // /// return doc as json
155     // /// It uses UF-16 codding
156     // export const(char*) doc_as_json(const uint32_t doc_id)
157     // {
158     //     auto doc = recyclerDoc(doc_id);
159     //     const json = doc.toJSON.toString();
160     //     return toStringz(json);
161     // }
162 
163     //     /// Getting the Document value from Document by index
164     // /// It uses UF-16 codding
165     // export uint64_t doc_get_docLen_by_id(const uint32_t doc_id, const uint32_t index)
166     // {
167     //     if (recyclerDoc(doc_id).hasMember(index))
168     //     {
169     //         const doc = recyclerDoc(doc_id)[index].get!Document;
170     //         return doc.serialize.length;
171     //     }
172     //     return BAD_RESULT;
173     // }
174 
175     // /// getting the Document value from Document by string key
176     // /// It uses UF-16 codding
177     export uint64_t doc_get_docLen_by_key(const uint32_t doc_id, const char* key_str, const uint32_t len) {
178         char[] key;
179         key.create(len);
180         for (int i = 0; i < len; i++) {
181             key[i] = key_str[i];
182         }
183         if (recyclerDoc(doc_id).hasMember(cast(string)(key))) {
184             const doc = recyclerDoc(doc_id)[cast(string) key].get!Document;
185             return doc.serialize.length;
186         }
187         return BAD_RESULT;
188     }
189 
190     // /// Getting the Document value from Document by index
191     // /// It uses UF-16 codding
192     // export uint8_t* doc_get_docPtr_by_id(const uint32_t doc_id, const uint32_t index)
193     // {
194     //     if (recyclerDoc(doc_id).hasMember(index))
195     //     {
196     //         const doc = recyclerDoc(doc_id)[index].get!Document;
197     //         return cast(ubyte*) doc.serialize.ptr;
198     //     }
199     //     return null;
200     // }
201 
202     // /// getting the Document value from Document by string key
203     // /// It uses UF-16 codding
204     export uint8_t* doc_get_docPtr_by_key(const uint32_t doc_id, const char* key_str, const uint32_t len) {
205         char[] key;
206         key.create(len);
207         for (int i = 0; i < len; i++) {
208             key[i] = key_str[i];
209         }
210         if (recyclerDoc(doc_id).hasMember(cast(string)(key))) {
211             const doc = recyclerDoc(doc_id)[cast(string) key].get!Document;
212             return cast(ubyte*) doc.serialize.ptr;
213         }
214         return null;
215     }
216 
217     // /// getting the Document value
218     // /// It uses UF-16 codding
219     export uint64_t get_docLen(const uint32_t doc_id) {
220         const doc = recyclerDoc(doc_id);
221         return doc.serialize.length;
222     }
223 
224     // /// getting the Document value
225     // /// It uses UF-16 codding
226     export uint8_t* get_docPtr(const uint32_t doc_id) {
227         const doc = recyclerDoc(doc_id);
228         return cast(ubyte*) doc.serialize.ptr;
229     }
230 
231     // export uint64_t doc_get_bufferLen_by_id(const uint32_t doc_id, const uint32_t index)
232     // {
233     //     if (recyclerDoc(doc_id).hasMember(index))
234     //     {
235     //         const buf = recyclerDoc(doc_id)[index].get!Buffer;
236     //         return buf.length;
237     //     }
238     //     return BAD_RESULT;
239     // }
240 
241     export uint64_t doc_get_bufferLen_by_key(const uint32_t doc_id, const char* key_str, const uint32_t len) {
242         char[] key;
243         key.create(len);
244         for (int i = 0; i < len; i++) {
245             key[i] = key_str[i];
246         }
247         if (recyclerDoc(doc_id).hasMember(cast(string)(key))) {
248             const buf = recyclerDoc(doc_id)[cast(string) key].get!Buffer;
249             return buf.length;
250         }
251         return BAD_RESULT;
252     }
253 
254     // export uint8_t* doc_get_bufferPtr_by_id(const uint32_t doc_id, const uint32_t index)
255     // {
256     //     if (recyclerDoc(doc_id).hasMember(index))
257     //     {
258     //         const doc = recyclerDoc(doc_id)[index].get!Buffer;
259     //         return cast(ubyte*) doc.ptr;
260     //     }
261     //     return null;
262     // }
263 
264     export uint8_t* doc_get_bufferPtr_by_key(const uint32_t doc_id, const char* key_str, const uint32_t len) {
265         char[] key;
266         key.create(len);
267         for (int i = 0; i < len; i++) {
268             key[i] = key_str[i];
269         }
270         if (recyclerDoc(doc_id).hasMember(cast(string)(key))) {
271             const doc = recyclerDoc(doc_id)[cast(string) key].get!Buffer;
272             return cast(ubyte*) doc.ptr;
273         }
274         return null;
275     }
276 
277     export uint64_t doc_get_memberCount(const uint32_t doc_id) {
278         return recyclerDoc(doc_id).length;
279     }
280     // /// Getting the keys of Document
281     // /// It uses UF-16 codding
282     // export const(char*) doc_get_keys(const uint32_t doc_id)
283     // {
284     //     if (recyclerDoc.exists(doc_id))
285     //     {
286     //         string[] keys = recyclerDoc(doc_id).keys();
287     //         string keysStr = join(keys, ";");
288     //         return toStringz(keysStr);
289     //     }
290     //     return null;
291     // }
292 
293     // unittest
294     // {
295     //     import std.stdio : writeln, writefln;
296     //     import std.string : fromStringz;
297     //     import tagion.hibon.HiBON : HiBON;
298 
299     //     // Aux HiBON for testing
300     //     auto hib = new HiBON;
301     //     hib["doc2"] = "test_str_with_key";
302 
303     //     // Tests for create_doc()
304     //     {
305     //         // Test for null request
306     //         assert(create_doc(null, 0) is 1);
307 
308     //         // Test for empty array
309     //         const(ubyte)[] empty_data = new ubyte[0];
310     //         assert(create_doc(empty_data.ptr, 0) is 2);
311 
312     //         // Tests for ubytes' sequence
313     //         const data1 = hib.serialize;
314     //         const data2 = hib.serialize;
315 
316     //         //assert(create_doc(data1.ptr, data1.length) is 2);
317     //         //assert(create_doc(data2.ptr, data2.length) is 3);
318     //     }
319 
320     //     // Tests for delete_doc_by_id()
321     //     {
322     //         delete_doc_by_id(1);
323     //         delete_doc_by_id(2);
324 
325     //         assert(!recyclerDoc.exists(0));
326     //         assert(!recyclerDoc.exists(1));
327 
328     //         // Append two docs and check whether they exists by indicies
329     //         const data = hib.serialize;
330     //         create_doc(data.ptr, cast(uint) data.length);
331     //         assert(recyclerDoc.exists(1));
332 
333     //         create_doc(data.ptr, cast(uint) data.length);
334     //         assert(recyclerDoc.exists(0));
335     //     }
336     //     // Range of Document' indexes in RecyclerDoc [0 .. 3]
337 
338     //     // Tests for doc_get_int_by_key()
339     //     {
340     //         assert(doc_get_int_by_key(0, "doc1", 4) is 100);
341     //         assert(doc_get_int_by_key(1, "doc1", 4) is 100);
342     //         assert(doc_get_int_by_key(2, "doc1", 4) is 100);
343     //         assert(doc_get_int_by_key(3, "doc1", 4) is 100);
344 
345     //         // Testing an absense of the key
346     //         assert(doc_get_int_by_key(0, "doc", 3) is BAD_RESULT);
347     //         assert(doc_get_int_by_key(1, "doc", 3) is BAD_RESULT);
348     //         assert(doc_get_int_by_key(2, "doc", 3) is BAD_RESULT);
349     //         assert(doc_get_int_by_key(3, "doc", 3) is BAD_RESULT);
350 
351     //         // Testing a wrong key size with correct key
352     //         assert(doc_get_int_by_key(0, "doc1", 3) is BAD_RESULT);
353     //         assert(doc_get_int_by_key(1, "doc1", 3) is BAD_RESULT);
354     //         assert(doc_get_int_by_key(2, "doc1", 3) is BAD_RESULT);
355     //         assert(doc_get_int_by_key(3, "doc1", 3) is BAD_RESULT);
356 
357     //         // Testing a wrong key size with incorrect key
358     //         assert(doc_get_int_by_key(0, "doc", 10) is BAD_RESULT);
359     //         assert(doc_get_int_by_key(1, "doc", 10) is BAD_RESULT);
360     //         assert(doc_get_int_by_key(2, "doc", 10) is BAD_RESULT);
361     //         assert(doc_get_int_by_key(3, "doc", 10) is BAD_RESULT);
362     //     }
363 
364     //     // Tests for doc_get_int_by_id()
365     //     {
366     //         assert(doc_get_int_by_id(0, 1) is 101);
367     //         assert(doc_get_int_by_id(1, 1) is 101);
368     //         assert(doc_get_int_by_id(2, 1) is 101);
369     //         assert(doc_get_int_by_id(3, 1) is 101);
370 
371     //         // Testing an absense of the key
372     //         assert(doc_get_int_by_id(0, 3) is BAD_RESULT);
373     //         assert(doc_get_int_by_id(1, 3) is BAD_RESULT);
374     //         assert(doc_get_int_by_id(2, 3) is BAD_RESULT);
375     //         assert(doc_get_int_by_id(3, 3) is BAD_RESULT);
376     //     }
377 
378     //     // Tests for doc_get_str_by_id()
379     //     {
380     //         const(char)[] expected_str = "test_str_with_id";
381 
382     //         assert(fromStringz(doc_get_str_by_id(0, 2)) == expected_str);
383     //         assert(fromStringz(doc_get_str_by_id(1, 2)) == expected_str);
384     //         assert(fromStringz(doc_get_str_by_id(2, 2)) == expected_str);
385     //         assert(fromStringz(doc_get_str_by_id(3, 2)) == expected_str);
386 
387     //         // Testing an existed document with wrong id
388     //         assert(doc_get_str_by_id(0, 0) is null);
389     //         assert(doc_get_str_by_id(1, 0) is null);
390     //         assert(doc_get_str_by_id(2, 0) is null);
391     //         assert(doc_get_str_by_id(3, 0) is null);
392     //     }
393 
394     //     // Tests for doc_get_str_by_key()
395     //     {
396     //         const(char)[] expected_str = "test_str_with_key";
397 
398     //         assert(fromStringz(doc_get_str_by_key(0, "doc2", 4)) == expected_str);
399     //         assert(fromStringz(doc_get_str_by_key(1, "doc2", 4)) == expected_str);
400     //         assert(fromStringz(doc_get_str_by_key(2, "doc2", 4)) == expected_str);
401     //         assert(fromStringz(doc_get_str_by_key(3, "doc2", 4)) == expected_str);
402 
403     //         // Testing an absense of the key
404     //         assert(doc_get_str_by_key(0, "doc", 3) is null);
405     //         assert(doc_get_str_by_key(1, "doc", 3) is null);
406     //         assert(doc_get_str_by_key(2, "doc", 3) is null);
407     //         assert(doc_get_str_by_key(3, "doc", 3) is null);
408 
409     //         // Testing a wrong key's size with correct key
410     //         assert(doc_get_str_by_key(0, "doc2", 3) is null);
411     //         assert(doc_get_str_by_key(1, "doc2", 3) is null);
412     //         assert(doc_get_str_by_key(2, "doc2", 3) is null);
413     //         assert(doc_get_str_by_key(3, "doc2", 3) is null);
414 
415     //         // Testing a wrong key's size with incorrect key
416     //         assert(doc_get_str_by_key(0, "doc", 10) is null);
417     //         assert(doc_get_str_by_key(1, "doc", 10) is null);
418     //         assert(doc_get_str_by_key(2, "doc", 10) is null);
419     //         assert(doc_get_str_by_key(3, "doc", 10) is null);
420     //     }
421 
422     //     {
423     //         import std.algorithm;
424     //         auto hib1 = new HiBON;
425     //         hib1["test"] = "test";
426     //         hib["doc3"] = Document(hib1);
427     //         const expected = hib1.serialize;
428 
429     //         const data = hib.serialize;
430     //         auto index = create_doc(data.ptr, cast(uint) data.length);
431 
432     //         const docLen = doc_get_docLen_by_key(index, "test", 4);
433     //         immutable docPtr = cast(immutable) doc_get_docPtr_by_key(index, "test", 4);
434     //         const doc = Document(docPtr[0..cast(uint)docLen]);
435     //         assert(equal(expected, doc.serialize));
436     //     }
437     // }
438 }