The OpenD Programming Language

1 /++
2 The module can be used for scripting languages to register a universal type serializer in the type system.
3 +/
4 module mir.ser.interfaces;
5 
6 /++
7 Unified serializer interface.
8 
9 ISerializer can be used in `serialize` method instead of generic serilizer.
10 
11 -----
12 struct S
13 {
14     void serialize(ISerializer serializer) const @safe
15     ...
16 -----
17 +/
18 interface ISerializer
19 {
20     import mir.bignum.decimal: Decimal;
21     import mir.bignum.integer: BigInt;
22     import mir.bignum.low_level_view: BigIntView;
23     import mir.ion.type_code: IonTypeCode;
24     import mir.lob: Blob, Clob;
25     import mir.timestamp : Timestamp;
26 
27 @safe pure scope:
28 
29     /++
30     Puts string part. The implementation allows to split string unicode points.
31     +/
32     void putStringPart(scope const(char)[] value);
33 
34     ///
35     void stringEnd(size_t state);
36 
37     ///
38     size_t structBegin(size_t length = size_t.max);
39 
40     ///
41     void structEnd(size_t state);
42 
43     ///
44     size_t listBegin(size_t length = size_t.max);
45 
46     ///
47     void listEnd(size_t state);
48 
49     ///
50     size_t sexpBegin(size_t length = size_t.max);
51 
52     ///
53     void sexpEnd(size_t state);
54 
55     ///
56     void putSymbol(scope const char[] symbol);
57 
58     ///
59     void putAnnotation(scope const(char)[] annotation);
60 
61     ///
62     size_t annotationsEnd(size_t state);
63 
64     ///
65     size_t annotationWrapperBegin();
66 
67     ///
68     void annotationWrapperEnd(size_t annotationsState, size_t state);
69 
70     ///
71     void nextTopLevelValue();
72 
73     ///
74     void putKey(scope const char[] key);
75 
76     ///
77     final void putValue(ubyte value)
78     {
79         putValue(ulong(value));
80     }
81 
82     ///
83     final void putValue(ushort value)
84     {
85         putValue(ulong(value));
86     }
87 
88     ///
89     final void putValue(uint value)
90     {
91         putValue(ulong(value));
92     }
93 
94     ///
95     final void putValue(byte value)
96     {
97         putValue(long(value));
98     }
99 
100     ///
101     final void putValue(short value)
102     {
103         putValue(long(value));
104     }
105 
106     ///
107     final void putValue(int value)
108     {
109         putValue(long(value));
110     }
111 
112     ///
113     void putValue(long value);
114 
115     ///
116     void putValue(ulong value);
117 
118     ///
119     void putValue(float value);
120 
121     ///
122     void putValue(double value);
123 
124     ///
125     void putValue(real value);
126 
127     ///
128     void putValue(scope ref const BigInt!128 value);
129 
130     ///
131     void putValue(scope ref const Decimal!128 value);
132 
133     ///
134     void putValue(typeof(null));
135 
136     /// ditto 
137     void putNull(IonTypeCode code);
138 
139     ///
140     void putValue(bool b);
141 
142     ///
143     void putValue(scope const char[] value);
144 
145     ///
146     void putValue(scope Clob value);
147 
148     ///
149     void putValue(scope Blob value);
150 
151     ///
152     void putValue(Timestamp value);
153 
154     ///
155     void elemBegin();
156 
157     ///
158     void sexpElemBegin();
159 
160     ///
161     int serdeTarget() nothrow const @property;
162 }
163 
164 /++
165 Serializer interface wrapper for common serializers.
166 +/
167 final class SerializerWrapper(S) : ISerializer
168 {
169     private S* serializer;
170 
171     ///
172     this(return scope ref S serializer) @trusted pure nothrow @nogc scope
173     {
174         this.serializer = &serializer;
175     }
176 
177 @safe pure scope:
178 
179     void putStringPart(scope const(char)[] value)
180     {
181         return serializer.putStringPart(value);
182     }
183 
184     void stringEnd(size_t state)
185     {
186         return serializer.stringEnd(state);
187     }
188 
189     size_t structBegin(size_t length = size_t.max)
190     {
191         return serializer.structBegin(length);
192     }
193 
194     void structEnd(size_t state)
195     {
196         return serializer.structEnd(state);
197     }
198 
199     size_t listBegin(size_t length = size_t.max)
200     {
201         return serializer.listBegin(length);
202     }
203 
204     void listEnd(size_t state)
205     {
206         return serializer.listEnd(state);
207     }
208 
209     size_t sexpBegin(size_t length = size_t.max)
210     {
211         return serializer.sexpBegin(length);
212     }
213 
214     void sexpEnd(size_t state)
215     {
216         return serializer.sexpEnd(state);
217     }
218 
219     void putSymbol(scope const char[] symbol)
220     {
221         return serializer.putSymbol(symbol);
222     }
223 
224     void putAnnotation(scope const(char)[] annotation)
225     {
226         return serializer.putAnnotation(annotation);
227     }
228 
229     size_t annotationsEnd(size_t state)
230     {
231         return serializer.annotationsEnd(state);
232     }
233 
234     size_t annotationWrapperBegin()
235     {
236         return serializer.annotationWrapperBegin();
237     }
238 
239     void annotationWrapperEnd(size_t annotationsState, size_t state)
240     {
241         return serializer.annotationWrapperEnd(annotationsState, state);
242     }
243 
244     void nextTopLevelValue()
245     {
246         return serializer.nextTopLevelValue();
247     }
248 
249     void putKey(scope const char[] key)
250     {
251         return serializer.putKey(key);
252     }
253 
254     void putValue(long value)
255     {
256         return serializer.putValue(value);
257     }
258 
259     void putValue(ulong value)
260     {
261         return serializer.putValue(value);
262     }
263 
264     void putValue(float value)
265     {
266         return serializer.putValue(value);
267     }
268 
269     void putValue(double value)
270     {
271         return serializer.putValue(value);
272     }
273 
274     void putValue(real value)
275     {
276         return serializer.putValue(value);
277     }
278 
279     void putValue(scope ref const BigInt!128 value)
280     {
281         return serializer.putValue(value);
282     }
283 
284     void putValue(scope ref const Decimal!128 value)
285     {
286         return serializer.putValue(value);
287     }
288 
289     void putValue(typeof(null))
290     {
291         return serializer.putValue(null);
292     }
293 
294     void putNull(IonTypeCode code)
295     {
296         return serializer.putNull(code);
297     }
298 
299     void putValue(bool value)
300     {
301         return serializer.putValue(value);
302     }
303 
304     void putValue(scope const char[] value)
305     {
306         return serializer.putValue(value);
307     }
308 
309     void putValue(scope Clob value)
310     {
311         return serializer.putValue(value);
312     }
313 
314     void putValue(scope Blob value)
315     {
316         return serializer.putValue(value);
317     }
318 
319     void putValue(Timestamp value)
320     {
321         return serializer.putValue(value);
322     }
323 
324     void elemBegin()
325     {
326         return serializer.elemBegin();
327     }
328 
329     void sexpElemBegin()
330     {
331         return serializer.sexpElemBegin();
332     }
333 
334     int serdeTarget() nothrow const @property
335     {
336         return serializer.serdeTarget;
337     }
338 }
339 
340 version(mir_ion_test)
341 unittest
342 {
343     static struct Wrapper(T)
344     {
345         T value;
346 
347         void serialize(S)(scope ref S serializer) scope const @safe
348         {
349             import mir.ser: serializeValue;
350             import mir.ser.interfaces: SerializerWrapper;
351             scope wserializer = new SerializerWrapper!S(serializer);
352             auto iserializer = wserializer.ISerializer;
353             serializeValue(iserializer, value);
354         }
355     }
356 
357     static auto wrap(T)(T value)
358     {
359         return Wrapper!T(value);
360     }
361 
362     import mir.ion.conv;
363     import mir.ser.ion;
364     import mir.ser.json;
365     import mir.ser.text;
366     import mir.ion.stream;
367     import std.datetime.date;
368 
369     assert(wrap(Date(1234, 5, 6)).serializeJson == `"1234-05-06"`);
370     assert(wrap(Date(1234, 5, 6)).serializeText == `1234-05-06`);
371     assert(wrap(Date(1234, 5, 6)).serializeIon.ion2text == `1234-05-06`);
372     immutable(ushort)[] imdata = [10, 20, 30];
373     assert(wrap(imdata).serializeIon.ion2text == `[10,20,30]`);
374 
375     const ubyte[] data = [0xe0, 0x01, 0x00, 0xea, 0xe9, 0x81, 0x83, 0xd6, 0x87, 0xb4, 0x81, 0x61, 0x81, 0x62, 0xd6, 0x8a, 0x21, 0x01, 0x8b, 0x21, 0x02];
376     auto json = wrap(data.IonValueStream).serializeJson;
377     assert(json == `{"a":1,"b":2}`);
378 }
379 
380 ///
381 version(mir_ion_test)
382 unittest
383 {
384     static struct Wrapper(T)
385     {
386         T value;
387 
388         void serialize(ISerializer serializer) const @safe
389         {
390             import mir.ser: serializeValue;
391             serializeValue(serializer, value);
392         }
393     }
394 
395     static auto wrap(T)(T value)
396     {
397         return Wrapper!T(value);
398     }
399 
400     import mir.ion.conv;
401     import mir.ser.ion;
402     import mir.ser.json;
403     import mir.ser.text;
404     import mir.ion.stream;
405     import std.datetime.date;
406 
407     assert(wrap(Date(1234, 5, 6)).serializeJson == `"1234-05-06"`);
408     assert(wrap(Date(1234, 5, 6)).serializeText == `1234-05-06`);
409     assert(wrap(Date(1234, 5, 6)).serializeIon.ion2text == `1234-05-06`);
410     immutable(ushort)[] imdata = [10, 20, 30];
411     assert(wrap(imdata).serializeIon.ion2text == `[10,20,30]`);
412 
413     const ubyte[] data = [0xe0, 0x01, 0x00, 0xea, 0xe9, 0x81, 0x83, 0xd6, 0x87, 0xb4, 0x81, 0x61, 0x81, 0x62, 0xd6, 0x8a, 0x21, 0x01, 0x8b, 0x21, 0x02];
414     auto json = wrap(data.IonValueStream).serializeJson;
415     assert(json == `{"a":1,"b":2}`);
416 }