1 /*
2  * hunt-proton: AMQP Protocol library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.proton.codec.impl.DataDecoder;
13 
14 
15 import hunt.io.ByteBuffer;
16 import hunt.proton.codec.Data;
17 import hunt.Exceptions;
18 import hunt.proton.amqp.UnsignedInteger;
19 import hunt.proton.amqp.UnsignedByte;
20 import hunt.proton.amqp.UnsignedShort;
21 import hunt.proton.amqp.UnsignedLong;
22 import hunt.proton.amqp.Decimal64;
23 import std.datetime.date;
24 import hunt.proton.amqp.Decimal32;
25 import hunt.proton.amqp.Decimal128;
26 import hunt.proton.amqp.Symbol;
27 import hunt.text.Charset;
28 import hunt.time.LocalDateTime;
29 import std.concurrency : initOnce;
30 import std.conv :to ;
31 
32 interface TypeConstructor
33 {
34     Data.DataType getType();
35 
36     int size(ByteBuffer b);
37 
38     void parse(ByteBuffer b, Data data);
39 }
40 
41 
42 class DataDecoder
43 {
44 
45     //private static Charset ASCII = StandardCharsets.US-ASCII;
46     //private static Charset UTF_8 = StandardCharsets.UTF-8;
47 
48      //TypeConstructor[] _constructors = new TypeConstructor[256];
49 
50 
51     static TypeConstructor[] _constructors()
52     {
53         __gshared TypeConstructor[] inst;
54         return initOnce!inst(initConstructors());
55     }
56     //
57     //private static UnsignedInteger[] initConstructor()
58     //{
59     //
60     //}
61 
62 
63     static TypeConstructor[] initConstructors()
64     {
65         TypeConstructor[] _constructors = new TypeConstructor[256];
66 
67         _constructors[0x00] = new DescribedTypeConstructor();
68 
69         _constructors[0x40] = new NullConstructor();
70         _constructors[0x41] = new TrueConstructor();
71         _constructors[0x42] = new FalseConstructor();
72         _constructors[0x43] = new UInt0Constructor();
73         _constructors[0x44] = new ULong0Constructor();
74         _constructors[0x45] = new EmptyListConstructor();
75 
76         _constructors[0x50] = new UByteConstructor();
77         _constructors[0x51] = new ByteConstructor();
78         _constructors[0x52] = new SmallUIntConstructor();
79         _constructors[0x53] = new SmallULongConstructor();
80         _constructors[0x54] = new SmallIntConstructor();
81         _constructors[0x55] = new SmallLongConstructor();
82         _constructors[0x56] = new BooleanConstructor();
83 
84         _constructors[0x60] = new UShortConstructor();
85         _constructors[0x61] = new ShortConstructor();
86 
87         _constructors[0x70] = new UIntConstructor();
88         _constructors[0x71] = new IntConstructor();
89         _constructors[0x72] = new FloatConstructor();
90         _constructors[0x73] = new CharConstructor();
91         _constructors[0x74] = new Decimal32Constructor();
92 
93         _constructors[0x80] = new ULongConstructor();
94         _constructors[0x81] = new LongConstructor();
95         _constructors[0x82] = new DoubleConstructor();
96         _constructors[0x83] = new TimestampConstructor();
97         _constructors[0x84] = new Decimal64Constructor();
98 
99         _constructors[0x94] = new Decimal128Constructor();
100         _constructors[0x98] = new UUIDConstructor();
101 
102         _constructors[0xa0] = new SmallBinaryConstructor();
103         _constructors[0xa1] = new SmallStringConstructor();
104         _constructors[0xa3] = new SmallSymbolConstructor();
105 
106         _constructors[0xb0] = new BinaryConstructor();
107         _constructors[0xb1] = new StringConstructor();
108         _constructors[0xb3] = new SymbolConstructor();
109 
110         _constructors[0xc0] = new SmallListConstructor();
111         _constructors[0xc1] = new SmallMapConstructor();
112 
113 
114         _constructors[0xd0] = new ListConstructor();
115         _constructors[0xd1] = new MapConstructor();
116 
117         _constructors[0xe0] = new SmallArrayConstructor();
118         _constructors[0xf0] = new ArrayConstructor();
119         return _constructors;
120     }
121 
122 
123 
124 
125     static int decode(ByteBuffer b, Data data)
126     {
127         if(b.hasRemaining())
128         {
129             int position = b.position();
130             TypeConstructor c = readConstructor(b);
131             int size = c.size(b);
132             if(b.remaining() >= size)
133             {
134                 c.parse(b, data);
135                 return 1+size;
136             }
137             else
138             {
139                 b.position(position);
140                 return -4;
141             }
142         }
143         return 0;
144     }
145 
146     static TypeConstructor readConstructor(ByteBuffer b)
147     {
148         int index = b.get() & 0xff;
149         TypeConstructor tc = _constructors[index];
150         if(tc is null)
151         {
152             throw new IllegalArgumentException("No constructor for type " ~ to!string(index));
153         }
154         return tc;
155     }
156 
157 
158 
159 
160 
161     static void parseChildren(Data data, ByteBuffer buf, int count)
162     {
163         data.enter();
164         for(int i = 0; i < count; i++)
165         {
166             TypeConstructor c = readConstructor(buf);
167             int size = c.size(buf);
168             int remaining = buf.remaining();
169             if(size <= remaining)
170             {
171                 c.parse(buf, data);
172             }
173             else
174             {
175                 throw new IllegalArgumentException("Malformed data");
176             }
177 
178         }
179         data.exit();
180     }
181 
182 
183 
184     private static void parseArray(Data data, ByteBuffer buf, int count)
185     {
186         byte type = buf.get();
187         bool isDescribed = type == cast(byte)0x00;
188         int descriptorPosition = buf.position();
189         if(isDescribed)
190         {
191             TypeConstructor descriptorTc = readConstructor(buf);
192             buf.position(buf.position()+descriptorTc.size(buf));
193             type = buf.get();
194             if(type == cast(byte)0x00)
195             {
196                 throw new IllegalArgumentException("Malformed array data");
197             }
198 
199         }
200         TypeConstructor tc = _constructors[type&0xff];
201 
202         data.putArray(isDescribed, tc.getType());
203         data.enter();
204         if(isDescribed)
205         {
206             int position = buf.position();
207             buf.position(descriptorPosition);
208             TypeConstructor descriptorTc = readConstructor(buf);
209             descriptorTc.parse(buf,data);
210             buf.position(position);
211         }
212         for(int i = 0; i<count; i++)
213         {
214             tc.parse(buf,data);
215         }
216 
217         data.exit();
218     }
219 
220 }
221 
222 class NullConstructor : TypeConstructor
223 {
224     override
225     public Data.DataType getType()
226     {
227         return Data.DataType.NULL;
228     }
229 
230     override
231     public int size(ByteBuffer b)
232     {
233         return 0;
234     }
235 
236     override
237     public void parse(ByteBuffer b, Data data)
238     {
239         data.putNull();
240     }
241 }
242 
243 class TrueConstructor : TypeConstructor
244 {
245     override
246     public Data.DataType getType()
247     {
248         return Data.DataType.BOOL;
249     }
250 
251     override
252     public int size(ByteBuffer b)
253     {
254         return 0;
255     }
256 
257     override
258     public void parse(ByteBuffer b, Data data)
259     {
260         data.putBoolean(true);
261     }
262 }
263 
264 
265 class FalseConstructor : TypeConstructor
266 {
267 
268     override
269     public Data.DataType getType()
270     {
271         return Data.DataType.BOOL;
272     }
273 
274     override
275     public int size(ByteBuffer b)
276     {
277         return 0;
278     }
279 
280     override
281     public void parse(ByteBuffer b, Data data)
282     {
283         data.putBoolean(false);
284     }
285 }
286 
287 class UInt0Constructor : TypeConstructor
288 {
289 
290     override
291     public Data.DataType getType()
292     {
293         return Data.DataType.UINT;
294     }
295 
296     override
297     public int size(ByteBuffer b)
298     {
299         return 0;
300     }
301 
302     override
303     public void parse(ByteBuffer b, Data data)
304     {
305         data.putUnsignedInteger(UnsignedInteger.ZERO);
306     }
307 }
308 
309 class ULong0Constructor : TypeConstructor
310 {
311 
312     override
313     public Data.DataType getType()
314     {
315         return Data.DataType.ULONG;
316     }
317 
318     override
319     public int size(ByteBuffer b)
320     {
321         return 0;
322     }
323 
324     override
325     public void parse(ByteBuffer b, Data data)
326     {
327         data.putUnsignedLong(UnsignedLong.ZERO);
328     }
329 }
330 
331 
332 class EmptyListConstructor : TypeConstructor
333 {
334 
335     override
336     public Data.DataType getType()
337     {
338         return Data.DataType.LIST;
339     }
340 
341     override
342     public int size(ByteBuffer b)
343     {
344         return 0;
345     }
346 
347     override
348     public void parse(ByteBuffer b, Data data)
349     {
350         data.putList();
351     }
352 }
353 
354 
355 abstract class Fixed0SizeConstructor : TypeConstructor
356 {
357     override
358     public int size(ByteBuffer b)
359     {
360         return 0;
361     }
362 }
363 
364 abstract class Fixed1SizeConstructor : TypeConstructor
365 {
366     override
367     public int size(ByteBuffer b)
368     {
369         return 1;
370     }
371 }
372 
373 abstract class Fixed2SizeConstructor : TypeConstructor
374 {
375     override
376     public int size(ByteBuffer b)
377     {
378         return 2;
379     }
380 }
381 
382 abstract class Fixed4SizeConstructor : TypeConstructor
383 {
384     override
385     public int size(ByteBuffer b)
386     {
387         return 4;
388     }
389 }
390 
391 abstract class Fixed8SizeConstructor : TypeConstructor
392 {
393     override
394     public int size(ByteBuffer b)
395     {
396         return 8;
397     }
398 }
399 
400 abstract class Fixed16SizeConstructor : TypeConstructor
401 {
402     override
403     public int size(ByteBuffer b)
404     {
405         return 16;
406     }
407 }
408 
409 class UByteConstructor : Fixed1SizeConstructor
410 {
411 
412     public Data.DataType getType()
413     {
414         return Data.DataType.UBYTE;
415     }
416 
417     public void parse(ByteBuffer b, Data data)
418     {
419         data.putUnsignedByte(UnsignedByte.valueOf(b.get()));
420     }
421 }
422 
423 class ByteConstructor : Fixed1SizeConstructor
424 {
425 
426     public Data.DataType getType()
427     {
428         return Data.DataType.BYTE;
429     }
430 
431     public void parse(ByteBuffer b, Data data)
432     {
433         data.putByte(b.get());
434     }
435 }
436 
437 class SmallUIntConstructor : Fixed1SizeConstructor
438 {
439 
440     public Data.DataType getType()
441     {
442         return Data.DataType.UINT;
443     }
444 
445     public void parse(ByteBuffer b, Data data)
446     {
447         data.putUnsignedInteger(UnsignedInteger.valueOf((cast(int) b.get()) & 0xff));
448     }
449 }
450 
451 class SmallIntConstructor : Fixed1SizeConstructor
452 {
453 
454     public Data.DataType getType()
455     {
456         return Data.DataType.INT;
457     }
458 
459     public void parse(ByteBuffer b, Data data)
460     {
461         data.putInt(b.get());
462     }
463 }
464 
465 class SmallULongConstructor : Fixed1SizeConstructor
466 {
467 
468     public Data.DataType getType()
469     {
470         return Data.DataType.ULONG;
471     }
472 
473     public void parse(ByteBuffer b, Data data)
474     {
475         data.putUnsignedLong(UnsignedLong.valueOf((cast(int) b.get()) & 0xff));
476     }
477 }
478 
479 class SmallLongConstructor : Fixed1SizeConstructor
480 {
481 
482     public Data.DataType getType()
483     {
484         return Data.DataType.LONG;
485     }
486 
487     public void parse(ByteBuffer b, Data data)
488     {
489         data.putLong(b.get());
490     }
491 }
492 
493 class BooleanConstructor : Fixed1SizeConstructor
494 {
495 
496     public Data.DataType getType()
497     {
498         return Data.DataType.BOOL;
499     }
500 
501     public void parse(ByteBuffer b, Data data)
502     {
503         int i = b.get();
504         if(i != 0 && i != 1)
505         {
506             throw new IllegalArgumentException("Illegal value " ~ to!string(i) ~ " for bool");
507         }
508         data.putBoolean(i == 1);
509     }
510 }
511 
512 class UShortConstructor : Fixed2SizeConstructor
513 {
514 
515     public Data.DataType getType()
516     {
517         return Data.DataType.USHORT;
518     }
519 
520     public void parse(ByteBuffer b, Data data)
521     {
522         data.putUnsignedShort(UnsignedShort.valueOf(b.getShort()));
523     }
524 }
525 
526 class ShortConstructor : Fixed2SizeConstructor
527 {
528 
529     public Data.DataType getType()
530     {
531         return Data.DataType.SHORT;
532     }
533 
534     public void parse(ByteBuffer b, Data data)
535     {
536         data.putShort(b.getShort());
537     }
538 }
539 
540 class UIntConstructor : Fixed4SizeConstructor
541 {
542 
543     public Data.DataType getType()
544     {
545         return Data.DataType.UINT;
546     }
547 
548     public void parse(ByteBuffer b, Data data)
549     {
550         data.putUnsignedInteger(UnsignedInteger.valueOf(b.getInt()));
551     }
552 }
553 
554 class IntConstructor : Fixed4SizeConstructor
555 {
556 
557     public Data.DataType getType()
558     {
559         return Data.DataType.INT;
560     }
561 
562     public void parse(ByteBuffer b, Data data)
563     {
564         data.putInt(b.getInt());
565     }
566 }
567 
568 class FloatConstructor : Fixed4SizeConstructor
569 {
570 
571     public Data.DataType getType()
572     {
573         return Data.DataType.FLOAT;
574     }
575 
576     public void parse(ByteBuffer b, Data data)
577     {
578         data.putFloat(cast(float)b.getInt());
579     }
580 }
581 
582 class CharConstructor : Fixed4SizeConstructor
583 {
584 
585     public Data.DataType getType()
586     {
587         return Data.DataType.CHAR;
588     }
589 
590     public void parse(ByteBuffer b, Data data)
591     {
592         data.putChar(b.getInt());
593     }
594 }
595 
596 class Decimal32Constructor : Fixed4SizeConstructor
597 {
598 
599     public Data.DataType getType()
600     {
601         return Data.DataType.DECIMAL32;
602     }
603 
604     public void parse(ByteBuffer b, Data data)
605     {
606         data.putDecimal32(new Decimal32(b.getInt()));
607     }
608 }
609 
610 class ULongConstructor : Fixed8SizeConstructor
611 {
612 
613     public Data.DataType getType()
614     {
615         return Data.DataType.ULONG;
616     }
617 
618     public void parse(ByteBuffer b, Data data)
619     {
620         data.putUnsignedLong(UnsignedLong.valueOf(b.getLong()));
621     }
622 }
623 
624 class LongConstructor : Fixed8SizeConstructor
625 {
626 
627     public Data.DataType getType()
628     {
629         return Data.DataType.LONG;
630     }
631 
632     public void parse(ByteBuffer b, Data data)
633     {
634         data.putLong(b.getLong());
635     }
636 }
637 
638 class DoubleConstructor : Fixed8SizeConstructor
639 {
640 
641     public Data.DataType getType()
642     {
643         return Data.DataType.DOUBLE;
644     }
645 
646     public void parse(ByteBuffer b, Data data)
647     {
648         data.putDouble(cast(double)b.getLong());
649     }
650 }
651 
652 class TimestampConstructor : Fixed8SizeConstructor
653 {
654 
655     public Data.DataType getType()
656     {
657         return Data.DataType.TIMESTAMP;
658     }
659 
660     public void parse(ByteBuffer b, Data data)
661     {
662         implementationMissing(false);
663         data.putTimestamp(hunt.time.LocalDateTime.LocalDateTime.ofEpochMilli(b.getLong()));
664     }
665 }
666 
667 class Decimal64Constructor : Fixed8SizeConstructor
668 {
669 
670     public Data.DataType getType()
671     {
672         return Data.DataType.DECIMAL64;
673     }
674 
675     public void parse(ByteBuffer b, Data data)
676     {
677         data.putDecimal64(new Decimal64(b.getLong()));
678     }
679 }
680 
681 class Decimal128Constructor : Fixed16SizeConstructor
682 {
683 
684     public Data.DataType getType()
685     {
686         return Data.DataType.DECIMAL128;
687     }
688 
689     public void parse(ByteBuffer b, Data data)
690     {
691         data.putDecimal128(new Decimal128(b.getLong(), b.getLong()));
692     }
693 }
694 
695 class UUIDConstructor : Fixed16SizeConstructor
696 {
697 
698     public Data.DataType getType()
699     {
700         return Data.DataType.UUID;
701     }
702 
703     public void parse(ByteBuffer b, Data data)
704     {
705        // data.putUUID(new UUID(b.getLong(), b.getLong()));
706     }
707 }
708 
709 abstract class SmallVariableConstructor : TypeConstructor
710 {
711 
712     public int size(ByteBuffer b)
713     {
714         int position = b.position();
715         if(b.hasRemaining())
716         {
717             int size = b.get() & 0xff;
718             b.position(position);
719 
720             return size+1;
721         }
722         else
723         {
724             return 1;
725         }
726     }
727 
728 }
729 
730 abstract class VariableConstructor : TypeConstructor
731 {
732 
733     public int size(ByteBuffer b)
734     {
735         int position = b.position();
736         if(b.remaining()>=4)
737         {
738             int size = b.getInt();
739             b.position(position);
740 
741             return size+4;
742         }
743         else
744         {
745             return 4;
746         }
747     }
748 
749 }
750 
751 
752 class SmallBinaryConstructor : SmallVariableConstructor
753 {
754 
755     public Data.DataType getType()
756     {
757         return Data.DataType.BINARY;
758     }
759 
760     public void parse(ByteBuffer b, Data data)
761     {
762         int size = b.get() & 0xff;
763         byte[] bytes = new byte[size];
764         b.get(bytes);
765         data.putBinary(bytes);
766     }
767 }
768 
769 class SmallSymbolConstructor : SmallVariableConstructor
770 {
771 
772     public Data.DataType getType()
773     {
774         return Data.DataType.SYMBOL;
775     }
776 
777     public void parse(ByteBuffer b, Data data)
778     {
779         int size = b.get() & 0xff;
780         byte[] bytes = new byte[size];
781         b.get(bytes);
782         data.putSymbol(Symbol.valueOf(cast(string)bytes));
783     }
784 }
785 
786 
787 class SmallStringConstructor : SmallVariableConstructor
788 {
789 
790     public Data.DataType getType()
791     {
792         return Data.DataType.STRING;
793     }
794 
795     public void parse(ByteBuffer b, Data data)
796     {
797         int size = b.get() & 0xff;
798         byte[] bytes = new byte[size];
799         b.get(bytes);
800         data.putString(cast(string)bytes);
801     }
802 }
803 
804 class BinaryConstructor : VariableConstructor
805 {
806     public Data.DataType getType()
807     {
808         return Data.DataType.BINARY;
809     }
810 
811     public void parse(ByteBuffer b, Data data)
812     {
813         int size = b.getInt();
814         byte[] bytes = new byte[size];
815         b.get(bytes);
816         data.putBinary(bytes);
817     }
818 }
819 
820 class SymbolConstructor : VariableConstructor
821 {
822 
823     public Data.DataType getType()
824     {
825         return Data.DataType.SYMBOL;
826     }
827 
828     public void parse(ByteBuffer b, Data data)
829     {
830         int size = b.getInt();
831         byte[] bytes = new byte[size];
832         b.get(bytes);
833         data.putSymbol(Symbol.valueOf(cast(string)bytes));
834     }
835 }
836 
837 
838 class StringConstructor : VariableConstructor
839 {
840 
841     public Data.DataType getType()
842     {
843         return Data.DataType.STRING;
844     }
845 
846     public void parse(ByteBuffer b, Data data)
847     {
848         int size = b.getInt();
849         byte[] bytes = new byte[size];
850         b.get(bytes);
851         data.putString(cast(string)bytes);
852     }
853 }
854 
855 
856 class SmallListConstructor : SmallVariableConstructor
857 {
858 
859     public Data.DataType getType()
860     {
861         return Data.DataType.LIST;
862     }
863 
864     public void parse(ByteBuffer b, Data data)
865     {
866         int size = b.get() & 0xff;
867         ByteBuffer buf = b.slice();
868         buf.limit(size);
869         b.position(b.position()+size);
870         int count = buf.get() & 0xff;
871         data.putList();
872         DataDecoder.parseChildren(data, buf, count);
873     }
874 }
875 
876 
877 class SmallMapConstructor : SmallVariableConstructor
878 {
879 
880     public Data.DataType getType()
881     {
882         return Data.DataType.MAP;
883     }
884 
885     public void parse(ByteBuffer b, Data data)
886     {
887         int size = b.get() & 0xff;
888         ByteBuffer buf = b.slice();
889         buf.limit(size);
890         b.position(b.position()+size);
891         int count = buf.get() & 0xff;
892         data.putMap();
893         DataDecoder.parseChildren(data, buf, count);
894     }
895 }
896 
897 
898 class ListConstructor : VariableConstructor
899 {
900     public Data.DataType getType()
901     {
902         return Data.DataType.LIST;
903     }
904     public void parse(ByteBuffer b, Data data)
905     {
906         int size = b.getInt();
907         ByteBuffer buf = b.slice();
908         buf.limit(size);
909         b.position(b.position()+size);
910         int count = buf.getInt();
911         data.putList();
912         DataDecoder.parseChildren(data, buf, count);
913     }
914 }
915 
916 
917 class MapConstructor : VariableConstructor
918 {
919 
920     public Data.DataType getType()
921     {
922         return Data.DataType.MAP;
923     }
924 
925     public void parse(ByteBuffer b, Data data)
926     {
927         int size = b.getInt();
928         ByteBuffer buf = b.slice();
929         buf.limit(size);
930         b.position(b.position()+size);
931         int count = buf.getInt();
932         data.putMap();
933         DataDecoder.parseChildren(data, buf, count);
934     }
935 }
936 class DescribedTypeConstructor : TypeConstructor
937 {
938 
939     public Data.DataType getType()
940     {
941         return Data.DataType.DESCRIBED;
942     }
943     public int size(ByteBuffer b)
944     {
945         ByteBuffer buf = b.slice();
946         if(buf.hasRemaining())
947         {
948             TypeConstructor c = DataDecoder.readConstructor(buf);
949             int size = c.size(buf);
950             if(buf.remaining()>size)
951             {
952                 buf.position(size + 1);
953                 c = DataDecoder.readConstructor(buf);
954                 return size + 2 + c.size(buf);
955             }
956             else
957             {
958                 return size + 2;
959             }
960         }
961         else
962         {
963             return 1;
964         }
965 
966     }
967 
968     public void parse(ByteBuffer b, Data data)
969     {
970         data.putDescribed();
971         data.enter();
972         TypeConstructor c = DataDecoder.readConstructor(b);
973         c.parse(b, data);
974         c = DataDecoder.readConstructor(b);
975         c.parse(b, data);
976         data.exit();
977     }
978 }
979 
980 class SmallArrayConstructor : SmallVariableConstructor
981 {
982 
983     public Data.DataType getType()
984     {
985         return Data.DataType.ARRAY;
986     }
987 
988     public void parse(ByteBuffer b, Data data)
989     {
990 
991         int size = b.get() & 0xff;
992         ByteBuffer buf = b.slice();
993         buf.limit(size);
994         b.position(b.position()+size);
995         int count = buf.get() & 0xff;
996         DataDecoder.parseArray(data, buf, count);
997     }
998 
999 }
1000 
1001 class ArrayConstructor : VariableConstructor
1002 {
1003 
1004     public Data.DataType getType()
1005     {
1006         return Data.DataType.ARRAY;
1007     }
1008 
1009 
1010     public void parse(ByteBuffer b, Data data)
1011     {
1012 
1013         int size = b.getInt();
1014         ByteBuffer buf = b.slice();
1015         buf.limit(size);
1016         b.position(b.position()+size);
1017         int count = buf.getInt();
1018         DataDecoder.parseArray(data, buf, count);
1019     }
1020 }