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 }