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.DecoderImpl;
13 
14 import hunt.io.ByteBuffer;
15 import hunt.collection.Collection;
16 import hunt.collection.Collections;
17 import hunt.time.LocalDateTime;
18 import hunt.collection.HashMap;
19 import hunt.collection.List;
20 import hunt.collection.Map;
21 import std.uuid;
22 
23 import hunt.proton.codec.PrimitiveType;
24 import hunt.proton.codec.EncodingCodes;
25 import hunt.proton.codec.TypeConstructor;
26 import hunt.proton.amqp.messaging.Section;
27 import hunt.proton.codec.FastPathDescribedTypeConstructor;
28 import hunt.proton.codec.DescribedTypeConstructor;
29 import hunt.proton.codec.PrimitiveTypeEncoding;
30 import hunt.proton.codec.ReadableBuffer;
31 import hunt.proton.codec.ByteBufferDecoder;
32 import hunt.Exceptions;
33 import hunt.proton.amqp.Binary;
34 import hunt.proton.amqp.Decimal128;
35 import hunt.proton.amqp.Decimal32;
36 import hunt.proton.amqp.Decimal64;
37 import hunt.proton.amqp.DescribedType;
38 import hunt.proton.amqp.Symbol;
39 import hunt.proton.amqp.UnsignedByte;
40 import hunt.proton.amqp.UnsignedInteger;
41 import hunt.proton.amqp.UnsignedLong;
42 import hunt.proton.amqp.UnsignedShort;
43 import hunt.proton.codec.DynamicTypeConstructor;
44 import hunt.proton.codec.AMQPType;
45 import hunt.proton.codec.TypeEncoding;
46 
47 import hunt.logging;
48 import hunt.Boolean;
49 import hunt.Short;
50 import hunt.Byte;
51 import hunt.Integer;
52 import hunt.Long;
53 import hunt.Char;
54 import hunt.Float;
55 import hunt.Double;
56 import hunt.String;
57 
58 
59 alias Date = LocalDateTime;
60 
61 
62 class DecoderImpl : ByteBufferDecoder
63 {
64     private ReadableBuffer _buffer;
65 
66    // private CharsetDecoder _charsetDecoder = StandardCharsets.UTF_8.newDecoder();
67 
68     private IPrimitiveTypeEncoding[] _constructors ;//= new IPrimitiveTypeEncoding[256];
69     //private Map!(Object, DescribedTypeConstructor) _dynamicTypeConstructors =
70     //        new HashMap!(Object, DescribedTypeConstructor)();
71 
72     //private Map!(Object, Object) _dynamicTypeConstructors =
73     //new HashMap!(Object, Object)();
74 
75 
76     private Map!(UnsignedLong,Object) _dynamicTypeConstructors_ul ;//= new HashMap!(UnsignedLong,Object);
77     private Map!(Symbol,Object) _dynamicTypeConstructors_sy  ;//= new HashMap!(Symbol,Object);
78 
79 
80     private Map!(UnsignedLong, Object) _fastPathTypeConstructors_ul;
81     private Map!(Symbol, Object) _fastPathTypeConstructors_sy;
82 
83     //private Map!(Object, FastPathDescribedTypeConstructor!Section) _fastPathTypeConstructors =
84     //    new HashMap!(Object, FastPathDescribedTypeConstructor!Section)();
85 
86     this()
87     {
88         _constructors = new IPrimitiveTypeEncoding[256];
89 
90         _dynamicTypeConstructors_ul = new HashMap!(UnsignedLong,Object);
91         _dynamicTypeConstructors_sy = new HashMap!(Symbol,Object);
92 
93         _fastPathTypeConstructors_ul = new HashMap!(UnsignedLong,Object);
94         _fastPathTypeConstructors_sy  = new HashMap!(Symbol,Object);
95     }
96 
97     this(ByteBuffer buffer)
98     {
99         _buffer = new ByteBufferReader(buffer);
100         _constructors = new IPrimitiveTypeEncoding[256];
101 
102         _dynamicTypeConstructors_ul = new HashMap!(UnsignedLong,Object);
103         _dynamicTypeConstructors_sy = new HashMap!(Symbol,Object);
104 
105         _fastPathTypeConstructors_ul = new HashMap!(UnsignedLong,Object);
106         _fastPathTypeConstructors_sy  = new HashMap!(Symbol,Object);
107 
108     }
109 
110     //public TypeConstructor<?> peekConstructor()
111     //{
112     //    _buffer.mark();
113     //    try
114     //    {
115     //        return readConstructor();
116     //    }
117     //    finally
118     //    {
119     //        _buffer.reset();
120     //    }
121     //}
122 
123     public ITypeConstructor readConstructor()
124     {
125         return readConstructor(false);
126     }
127 
128     public ITypeConstructor readConstructor(bool excludeFastPathConstructors)
129     {
130         //implementationMissing(false);
131         //return null;
132         int code = (cast(int)readRawByte()) & 0xff;
133         if(code == EncodingCodes.DESCRIBED_TYPE_INDICATOR)
134         {
135             byte encoding = _buffer.get(_buffer.position());
136             Object descriptor;
137 
138             int flag = 0;
139 
140             if (EncodingCodes.SMALLULONG == encoding || EncodingCodes.ULONG == encoding)
141             {
142                 descriptor = readUnsignedLong(null);
143                 UnsignedLong dd = cast(UnsignedLong)descriptor;
144              //   logInfo("descriptor:%d",dd.intValue());
145                 flag = 0;
146             }
147             else if (EncodingCodes.SYM8 == encoding || EncodingCodes.SYM32 == encoding)
148             {
149                 descriptor = readSymbol(null);
150                 flag = 1;
151             }
152             else
153             {
154                 descriptor = readObject();
155             }
156 
157             if (!excludeFastPathConstructors)
158             {
159                 Object fastPathTypeConstructor;
160                 if (flag == 0)
161                 {
162                     UnsignedLong ul = cast(UnsignedLong)descriptor;
163                     fastPathTypeConstructor = _fastPathTypeConstructors_ul.get(ul);
164 
165 
166                 } else
167                 {
168                     Symbol sy = cast(Symbol)descriptor;
169                     fastPathTypeConstructor = _fastPathTypeConstructors_sy.get(sy);
170                 }
171                 if (fastPathTypeConstructor !is null)
172                 {
173                     return cast(ITypeConstructor)fastPathTypeConstructor;
174                 }
175             }
176 
177             ITypeConstructor nestedEncoding = readConstructor(false);
178 
179 
180             Object dtc ;
181 
182             if (flag == 0 )
183             {
184                dtc =  _dynamicTypeConstructors_ul.get(cast(UnsignedLong)descriptor);
185             }else
186             {
187                 dtc =  _dynamicTypeConstructors_sy.get(cast(Symbol)descriptor);
188             }
189 
190             if(dtc is null)
191             {
192                 dtc = new class DescribedTypeConstructor!UnknownDescribedType
193                 {
194                     public UnknownDescribedType newInstance(Object described)
195                     {
196                         return new UnknownDescribedType(descriptor, described);
197                     }
198 
199                     public TypeInfo getTypeClass()
200                     {
201                         return typeid(UnknownDescribedType);
202                     }
203                 };
204                 registerDynamic(descriptor, dtc);
205             }
206             return new DynamicTypeConstructor(cast(IDescribedTypeConstructor)dtc, nestedEncoding);
207         }
208         else
209         {
210             return cast(ITypeConstructor)(_constructors[code]);
211         }
212     }
213 
214     override
215     public void registerFastPath(Object descriptor, Object btc)
216     {
217         UnsignedLong ul = cast(UnsignedLong)descriptor;
218         if (ul !is null)
219         {
220             _fastPathTypeConstructors_ul.put(ul, btc);
221             return;
222         }
223 
224         Symbol sy = cast(Symbol)descriptor;
225         if(sy !is null)
226         {
227             _fastPathTypeConstructors_sy.put(sy,btc);
228         }
229        // _fastPathTypeConstructors.put(descriptor, btc);
230     }
231 
232     override
233     public void registerDynamic(Object descriptor, Object dtc)
234     {
235         // Allow external type constructors to replace the built-in instances.
236         UnsignedLong ul = cast(UnsignedLong)descriptor;
237         if (ul !is null)
238         {
239             _fastPathTypeConstructors_ul.remove(ul);
240             _dynamicTypeConstructors_ul.put(ul,dtc);
241             return;
242         }
243         Symbol sy = cast(Symbol)descriptor;
244         if(sy !is null)
245         {
246             _fastPathTypeConstructors_sy.remove(sy);
247             _dynamicTypeConstructors_sy.put(sy,dtc);
248         }
249     }
250 
251     //private ClassCastException unexpectedType(Object val, Class clazz)
252     //{
253     //    return new ClassCastException("Unexpected type "
254     //                                  + val.getClass().getName()
255     //                                  ~ ". Expected "
256     //                                  + clazz.getName() +".");
257     //}
258 
259     public Boolean readBoolean()
260     {
261         return readBoolean(null);
262     }
263 
264     public Boolean readBoolean(Boolean defaultVal)
265     {
266         byte encodingCode = _buffer.get();
267 
268         switch (encodingCode)
269         {
270             case EncodingCodes.BOOLEAN_TRUE:
271                 return Boolean.TRUE;
272             case EncodingCodes.BOOLEAN_FALSE:
273                 return Boolean.FALSE;
274             case EncodingCodes.BOOLEAN:
275                 return readRawByte() == 0 ? Boolean.FALSE : Boolean.TRUE;
276             case EncodingCodes.NULL:
277                 return defaultVal;
278             default:
279             {
280                 logError("Expected bool type but found encoding");
281                 return null;
282             }
283 
284                // throw new DecodeException("Expected bool type but found encoding: " ~ encodingCode);
285         }
286     }
287 
288     public bool readBoolean(bool defaultVal)
289     {
290         byte encodingCode = _buffer.get();
291 
292         switch (encodingCode)
293         {
294             case EncodingCodes.BOOLEAN_TRUE:
295                 return true;
296             case EncodingCodes.BOOLEAN_FALSE:
297                 return false;
298             case EncodingCodes.BOOLEAN:
299                 return readRawByte() != 0;
300             case EncodingCodes.NULL:
301                 return defaultVal;
302             default:
303             {
304                 logError("Expected bool type but found encoding");
305                 return false;
306             }
307               //  throw new DecodeException("Expected bool type but found encoding: " ~ encodingCode);
308         }
309     }
310 
311     public Byte readByte()
312     {
313         return readByte(null);
314     }
315 
316     public Byte readByte(Byte defaultVal)
317     {
318         byte encodingCode = _buffer.get();
319 
320         switch (encodingCode) {
321             case EncodingCodes.BYTE:
322                 return new Byte(readRawByte());
323             case EncodingCodes.NULL:
324                 return defaultVal;
325             default:
326             {
327                 logError("Expected byte type but found encoding");
328                 return null;
329             }
330                // throw new DecodeException("Expected byte type but found encoding: " ~ encodingCode);
331         }
332     }
333 
334     public byte readByte(byte defaultVal)
335     {
336 
337         implementationMissing(false);
338         return defaultVal;
339         //TypeConstructor<?> constructor = readConstructor();
340         //if(constructor instanceof ByteType.ByteEncoding)
341         //{
342         //    return ((ByteType.ByteEncoding)constructor).readPrimitiveValue();
343         //}
344         //else
345         //{
346         //    Object val = constructor.readValue();
347         //    if(val is null)
348         //    {
349         //        return defaultVal;
350         //    }
351         //    else
352         //    {
353         //        throw unexpectedType(val, Byte.class);
354         //    }
355         //}
356     }
357 
358     public Short readShort()
359     {
360         return readShort(null);
361     }
362 
363     public Short readShort(Short defaultVal)
364     {
365         byte encodingCode = _buffer.get();
366 
367         switch (encodingCode)
368         {
369             case EncodingCodes.SHORT:
370                 return new Short(readRawShort());
371             case EncodingCodes.NULL:
372                 return defaultVal;
373             default:
374             {
375                 logError("Expected Short type but found encoding:");
376                 return null;
377             }
378                 //throw new DecodeException("Expected Short type but found encoding: " ~ encodingCode);
379         }
380     }
381 
382     public short readShort(short defaultVal)
383     {
384         implementationMissing(false);
385         return defaultVal;
386         //TypeConstructor<?> constructor = readConstructor();
387         //if(constructor instanceof ShortType.ShortEncoding)
388         //{
389         //    return ((ShortType.ShortEncoding)constructor).readPrimitiveValue();
390         //}
391         //else
392         //{
393         //    Object val = constructor.readValue();
394         //    if(val is null)
395         //    {
396         //        return defaultVal;
397         //    }
398         //    else
399         //    {
400         //        throw unexpectedType(val, Short.class);
401         //    }
402         //}
403     }
404 
405     public Integer readInteger()
406     {
407         return readInteger(null);
408     }
409 
410     public Integer readInteger(Integer defaultVal)
411     {
412         byte encodingCode = _buffer.get();
413 
414         switch (encodingCode)
415         {
416             case EncodingCodes.SMALLINT:
417                 return Integer.valueOf(readRawByte());
418             case EncodingCodes.INT:
419                 return Integer.valueOf(readRawInt());
420             case EncodingCodes.NULL:
421                 return defaultVal;
422             default:
423             {
424                 logError("Expected Integer type but found encoding:");
425                 return null;
426             }
427               //  throw new DecodeException("Expected Integer type but found encoding: " ~ encodingCode);
428         }
429     }
430 
431     public int readInteger(int defaultVal)
432     {
433         implementationMissing(false);
434         //TypeConstructor<?> constructor = readConstructor();
435         //if(constructor instanceof IntegerType.IntegerEncoding)
436         //{
437         //    return ((IntegerType.IntegerEncoding)constructor).readPrimitiveValue();
438         //}
439         //else
440         //{
441         //    Object val = constructor.readValue();
442         //    if(val is null)
443         //    {
444         //        return defaultVal;
445         //    }
446         //    else
447         //    {
448         //        throw unexpectedType(val, Integer.class);
449         //    }
450         //}
451         return 0;
452     }
453 
454     public Long readLong()
455     {
456         return readLong(null);
457     }
458 
459     public Long readLong(Long defaultVal)
460     {
461         byte encodingCode = _buffer.get();
462 
463         switch (encodingCode)
464         {
465             case EncodingCodes.SMALLLONG:
466                 return Long.valueOf(readRawByte());
467             case EncodingCodes.LONG:
468                 return Long.valueOf(readRawLong());
469             case EncodingCodes.NULL:
470                 return defaultVal;
471             default:
472             {
473                 logError("Expected Long type but found encoding");
474                 return null;
475             }
476                // throw new DecodeException("Expected Long type but found encoding: " ~ encodingCode);
477         }
478     }
479 
480     public long readLong(long defaultVal)
481     {
482         implementationMissing(false);
483         //TypeConstructor<?> constructor = readConstructor();
484         //if(constructor instanceof LongType.LongEncoding)
485         //{
486         //    return ((LongType.LongEncoding)constructor).readPrimitiveValue();
487         //}
488         //else
489         //{
490         //    Object val = constructor.readValue();
491         //    if(val is null)
492         //    {
493         //        return defaultVal;
494         //    }
495         //    else
496         //    {
497         //        throw unexpectedType(val, Long.class);
498         //    }
499         //}
500         return 0;
501     }
502 
503     public UnsignedByte readUnsignedByte()
504     {
505         return readUnsignedByte(null);
506     }
507 
508     public UnsignedByte readUnsignedByte(UnsignedByte defaultVal)
509     {
510         byte encodingCode = _buffer.get();
511 
512         switch (encodingCode)
513         {
514             case EncodingCodes.UBYTE:
515                 return UnsignedByte.valueOf(readRawByte());
516             case EncodingCodes.NULL:
517                 return defaultVal;
518             default:
519             {
520                 logError("Expected unsigned byte type but found encoding");
521                 return null;
522             }
523                // throw new DecodeException("Expected unsigned byte type but found encoding: " ~ encodingCode);
524         }
525     }
526 
527 
528     public UnsignedShort readUnsignedShort()
529     {
530         return readUnsignedShort(null);
531     }
532 
533     public UnsignedShort readUnsignedShort(UnsignedShort defaultVal)
534     {
535         byte encodingCode = _buffer.get();
536 
537         switch (encodingCode)
538         {
539             case EncodingCodes.USHORT:
540                 return UnsignedShort.valueOf(readRawShort());
541             case EncodingCodes.NULL:
542                 return defaultVal;
543             default:
544             {
545                 logError("Expected UnsignedShort type but found encoding:");
546                 return null;
547             }
548                // throw new DecodeException("Expected UnsignedShort type but found encoding: " ~ encodingCode);
549         }
550     }
551 
552     public UnsignedInteger readUnsignedInteger()
553     {
554         return readUnsignedInteger(null);
555     }
556 
557     public UnsignedInteger readUnsignedInteger(UnsignedInteger defaultVal)
558     {
559         byte encodingCode = _buffer.get();
560 
561         switch (encodingCode)
562         {
563             case EncodingCodes.UINT0:
564                 return UnsignedInteger.ZERO;
565             case EncodingCodes.SMALLUINT:
566                 return UnsignedInteger.valueOf((cast(int) readRawByte()) & 0xff);
567             case EncodingCodes.UINT:
568                 return UnsignedInteger.valueOf(readRawInt());
569             case EncodingCodes.NULL:
570                 return defaultVal;
571             default:
572             {
573                 logError("Expected UnsignedInteger type but found encoding");
574                 return null;
575             }
576                 //throw new DecodeException("Expected UnsignedInteger type but found encoding: " ~ encodingCode);
577         }
578     }
579 
580     public UnsignedLong readUnsignedLong()
581     {
582         return readUnsignedLong(null);
583     }
584 
585     public UnsignedLong readUnsignedLong(UnsignedLong defaultVal)
586     {
587         byte encodingCode = _buffer.get();
588 
589         switch (encodingCode)
590         {
591             case EncodingCodes.ULONG0:
592                 return UnsignedLong.ZERO;
593             case EncodingCodes.SMALLULONG:
594                 return UnsignedLong.valueOf((cast(long) readRawByte())&0xff);
595             case EncodingCodes.ULONG:
596                 return UnsignedLong.valueOf(readRawLong());
597             case EncodingCodes.NULL:
598                 return defaultVal;
599             default:
600             {
601                 logError("Expected UnsignedLong type but found encoding");
602                 return null;
603             }
604                // throw new DecodeException("Expected UnsignedLong type but found encoding: " ~ encodingCode);
605         }
606     }
607 
608     public Char readCharacter()
609     {
610         return readCharacter(null);
611     }
612 
613     public Char readCharacter(Char defaultVal)
614     {
615         byte encodingCode = _buffer.get();
616 
617         switch (encodingCode)
618         {
619             case EncodingCodes.CHAR:
620                 return Char.valueOf(cast(char) (readRawInt() & 0xffff));
621             case EncodingCodes.NULL:
622                 return defaultVal;
623             default:
624             {
625                 logError("Expected Character type but found encoding");
626                 return null;
627             }
628                 //throw new DecodeException("Expected Character type but found encoding: " ~ encodingCode);
629         }
630     }
631 
632     public char readCharacter(char defaultVal)
633     {
634         byte encodingCode = _buffer.get();
635 
636         switch (encodingCode)
637         {
638             case EncodingCodes.CHAR:
639                 return cast(char) (readRawInt() & 0xffff);
640             case EncodingCodes.NULL:
641                 return defaultVal;
642             default:
643             {
644                 logError("Expected Character type but found encoding");
645                 return defaultVal;
646             }
647                // throw new DecodeException("Expected Character type but found encoding: " ~ encodingCode);
648         }
649     }
650 
651 
652     public Float readFloat()
653     {
654         return readFloat(null);
655     }
656 
657 
658     public Float readFloat(Float defaultVal)
659     {
660         byte encodingCode = _buffer.get();
661 
662         switch (encodingCode)
663         {
664             case EncodingCodes.FLOAT:
665                 return Float.valueOf(readRawFloat());
666             case EncodingCodes.NULL:
667                 return defaultVal;
668             default:
669             {
670                 logError("Expected Float type but found encoding:");
671                 return null;
672             }
673               //  throw new ProtonException("Expected Float type but found encoding: " ~ encodingCode);
674         }
675     }
676 
677 
678     public float readFloat(float defaultVal)
679     {
680         implementationMissing(false);
681         return defaultVal;
682         //TypeConstructor<?> constructor = readConstructor();
683         //if(constructor instanceof FloatType.FloatEncoding)
684         //{
685         //    return ((FloatType.FloatEncoding)constructor).readPrimitiveValue();
686         //}
687         //else
688         //{
689         //    Object val = constructor.readValue();
690         //    if(val is null)
691         //    {
692         //        return defaultVal;
693         //    }
694         //    else
695         //    {
696         //        throw unexpectedType(val, Float.class);
697         //    }
698         //}
699     }
700 
701 
702     public Double readDouble()
703     {
704         return readDouble(null);
705     }
706 
707 
708     public Double readDouble(Double defaultVal)
709     {
710         byte encodingCode = _buffer.get();
711 
712         switch (encodingCode)
713         {
714             case EncodingCodes.DOUBLE:
715                 return Double.valueOf(readRawDouble());
716             case EncodingCodes.NULL:
717                 return defaultVal;
718             default:
719             {
720                 logError("Expected Double type but found encoding");
721                 return null;
722             }
723              //   throw new ProtonException("Expected Double type but found encoding: " ~ encodingCode);
724         }
725     }
726 
727 
728     public double readDouble(double defaultVal)
729     {
730 
731 
732         implementationMissing(false);
733         return defaultVal;
734         //TypeConstructor<?> constructor = readConstructor();
735         //if(constructor instanceof DoubleType.DoubleEncoding)
736         //{
737         //    return ((DoubleType.DoubleEncoding)constructor).readPrimitiveValue();
738         //}
739         //else
740         //{
741         //    Object val = constructor.readValue();
742         //    if(val is null)
743         //    {
744         //        return defaultVal;
745         //    }
746         //    else
747         //    {
748         //        throw unexpectedType(val, Double.class);
749         //    }
750         //}
751     }
752 
753 
754     public UUID readUUID()
755     {
756        // return readUUID(null);
757         UUID id;
758         return id;
759     }
760 
761 
762     public UUID readUUID(UUID defaultVal)
763     {
764         implementationMissing(false);
765         byte encodingCode = _buffer.get();
766 
767         switch (encodingCode)
768         {
769             case EncodingCodes.UUID:
770                 //return  UUID(readRawLong(), readRawLong());
771                 return defaultVal;
772             case EncodingCodes.NULL:
773                 return defaultVal;
774             default:
775             {
776                 logError("Expected UUID type but found encoding");
777                 return defaultVal;
778             }
779                 //throw new ProtonException("Expected UUID type but found encoding: " ~ encodingCode);
780         }
781     }
782 
783 
784     public Decimal32 readDecimal32()
785     {
786         return readDecimal32(null);
787     }
788 
789 
790     public Decimal32 readDecimal32(Decimal32 defaultValue)
791     {
792         implementationMissing(false);
793         byte encodingCode = _buffer.get();
794 
795         switch (encodingCode)
796         {
797             case EncodingCodes.DECIMAL32:
798                // return cast(Decimal32) _constructors[EncodingCodes.DECIMAL32 & 0xff].readValue();
799             return defaultValue;
800             case EncodingCodes.NULL:
801                 return defaultValue;
802             default:
803             {
804                 logError("Expected Decimal32 type but found encoding");
805                 return null;
806             }
807               //  throw new ProtonException("Expected Decimal32 type but found encoding: " ~ encodingCode);
808         }
809     }
810 
811 
812     public Decimal64 readDecimal64()
813     {
814         return readDecimal64(null);
815     }
816 
817 
818     public Decimal64 readDecimal64(Decimal64 defaultValue)
819     {
820         implementationMissing(false);
821         byte encodingCode = _buffer.get();
822 
823         switch (encodingCode)
824         {
825             case EncodingCodes.DECIMAL64:
826                 //return cast(Decimal64) _constructors[EncodingCodes.DECIMAL64 & 0xff].readValue();
827             return defaultValue;
828             case EncodingCodes.NULL:
829                 return defaultValue;
830             default:
831             {
832                 logError("Expected Decimal64 type but found encoding");
833                 return null;
834             }
835                // throw new ProtonException("Expected Decimal64 type but found encoding: " ~ encodingCode);
836         }
837     }
838 
839 
840     public Decimal128 readDecimal128()
841     {
842         return readDecimal128(null);
843     }
844 
845 
846     public Decimal128 readDecimal128(Decimal128 defaultValue)
847     {
848         implementationMissing(false);
849         byte encodingCode = _buffer.get();
850 
851         switch (encodingCode)
852         {
853             case EncodingCodes.DECIMAL128:
854               //  return cast(Decimal128) _constructors[EncodingCodes.DECIMAL128 & 0xff].readValue();
855             return defaultValue;
856             case EncodingCodes.NULL:
857                 return defaultValue;
858             default:
859             {
860                 logError("Expected Decimal128 type but found encoding");
861                 return null;
862             }
863                 //throw new ProtonException("Expected Decimal128 type but found encoding: " ~ encodingCode);
864         }
865     }
866 
867 
868     public Date readTimestamp()
869     {
870         return readTimestamp(null);
871     }
872 
873 
874     public Date readTimestamp(Date defaultValue)
875     {
876         byte encodingCode = _buffer.get();
877 
878         switch (encodingCode)
879         {
880             case EncodingCodes.TIMESTAMP:
881                 return  Date.ofEpochMilli(readRawLong());
882             case EncodingCodes.NULL:
883                 return defaultValue;
884             default:
885             {
886                 logError("Expected Timestamp type but found encoding");
887                 return null;
888             }
889                // throw new ProtonException("Expected Timestamp type but found encoding: " ~ encodingCode);
890         }
891     }
892 
893 
894     public Binary readBinary()
895     {
896         return readBinary(null);
897     }
898 
899 
900     public Binary readBinary(Binary defaultValue)
901     {
902         byte encodingCode = _buffer.get();
903 
904         switch (encodingCode)
905         {
906             case EncodingCodes.VBIN8:
907                 return cast(Binary)((cast(TypeConstructor!Binary) _constructors[EncodingCodes.VBIN8 & 0xff]).readValue());
908                 //return defaultValue;
909             case EncodingCodes.VBIN32:
910                 return cast(Binary)((cast(TypeConstructor!Binary) _constructors[EncodingCodes.VBIN32 & 0xff]).readValue());
911                // return defaultValue;
912             case EncodingCodes.NULL:
913                 return defaultValue;
914             default:
915             {
916                 logError("Expected Binary type but found encoding");
917                 return null;
918             }
919                 //throw new ProtonException("Expected Binary type but found encoding: " ~ encodingCode);
920         }
921     }
922 
923 
924     public Symbol readSymbol()
925     {
926         return readSymbol(null);
927     }
928 
929 
930     public Symbol readSymbol(Symbol defaultValue)
931     {
932         byte encodingCode = _buffer.get();
933 
934         switch (encodingCode)
935         {
936             case EncodingCodes.SYM8:
937                 return cast(Symbol)((cast(TypeConstructor!Symbol) (_constructors[EncodingCodes.SYM8 & 0xff])).readValue());
938                 //return defaultValue;
939             case EncodingCodes.SYM32:
940                 return  cast(Symbol)((cast(TypeConstructor!Symbol) (_constructors[EncodingCodes.SYM32 & 0xff])).readValue());
941                 //return defaultValue;
942             case EncodingCodes.NULL:
943                 return defaultValue;
944             default:
945             {
946                 logError("Expected Symbol type but found encoding");
947                 return null;
948             }
949                // throw new ProtonException("Expected Symbol type but found encoding: " ~ encodingCode);
950         }
951     }
952 
953 
954     public String readString()
955     {
956         return readString(null);
957     }
958 
959 
960     public String readString(String defaultValue)
961     {
962         byte encodingCode = _buffer.get();
963 
964         switch (encodingCode)
965         {
966             case EncodingCodes.STR8:
967                 return cast(String)((cast(TypeConstructor!String) _constructors[EncodingCodes.STR8 & 0xff]).readValue());
968                 //return defaultValue;
969             case EncodingCodes.STR32:
970                 return cast(String)((cast(TypeConstructor!String) _constructors[EncodingCodes.STR32 & 0xff]).readValue());
971                 //return defaultValue;
972             case EncodingCodes.NULL:
973                 return defaultValue;
974             default:
975             {
976                 logError("Expected String type but found encoding");
977                 return null;
978             }
979               //  throw new ProtonException("Expected String type but found encoding: " ~ encodingCode);
980         }
981     }
982 
983     //
984     //@SuppressWarnings("rawtypes")
985     //public List readList()
986     //{
987     //    byte encodingCode = _buffer.get();
988     //
989     //    switch (encodingCode)
990     //    {
991     //        case EncodingCodes.LIST0:
992     //            return Collections.EMPTY_LIST;
993     //        case EncodingCodes.LIST8:
994     //            return cast(List) _constructors[EncodingCodes.LIST8 & 0xff].readValue();
995     //        case EncodingCodes.LIST32:
996     //            return cast(List) _constructors[EncodingCodes.LIST32 & 0xff].readValue();
997     //        case EncodingCodes.NULL:
998     //            return null;
999     //        default:
1000     //            throw new ProtonException("Expected List type but found encoding: " ~ encodingCode);
1001     //    }
1002     //}
1003     //
1004     //
1005     //public <T> void readList(ListProcessor!(T) processor)
1006     //{
1007     //    //TODO.
1008     //}
1009 
1010     //
1011     //@SuppressWarnings("rawtypes")
1012     public Object readMap()
1013     {
1014         byte encodingCode = _buffer.get();
1015 
1016         switch (encodingCode)
1017         {
1018             case EncodingCodes.MAP8:
1019                 return cast(Object)(cast(ITypeConstructor)(_constructors[EncodingCodes.MAP8 & 0xff])).readValue();
1020             case EncodingCodes.MAP32:
1021                 return cast(Object)(cast(ITypeConstructor)(_constructors[EncodingCodes.MAP32 & 0xff])).readValue();
1022             case EncodingCodes.NULL:
1023                 return null;
1024             default:
1025             {
1026                 logError("Expected Map type but found encoding");
1027                 return null;
1028             }
1029                // throw new ProtonException("Expected Map type but found encoding: " ~ encodingCode);
1030         }
1031     }
1032     //
1033     //
1034     //public <T> T[] readArray(Class!(T) clazz)
1035     //{
1036     //    return null;  //TODO.
1037     //}
1038 
1039     //
1040     //public Object[] readArray()
1041     //{
1042     //    return (Object[]) readConstructor().readValue();
1043     //
1044     //}
1045 
1046     //
1047     //public bool[] readBooleanArray()
1048     //{
1049     //    return (bool[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
1050     //}
1051     //
1052     //
1053     //public byte[] readByteArray()
1054     //{
1055     //    return (byte[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
1056     //}
1057     //
1058     //
1059     //public short[] readShortArray()
1060     //{
1061     //    return (short[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
1062     //}
1063     //
1064     //
1065     //public int[] readIntegerArray()
1066     //{
1067     //    return (int[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
1068     //}
1069     //
1070     //
1071     //public long[] readLongArray()
1072     //{
1073     //    return (long[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
1074     //}
1075     //
1076     //
1077     //public float[] readFloatArray()
1078     //{
1079     //    return (float[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
1080     //}
1081     //
1082     //
1083     //public double[] readDoubleArray()
1084     //{
1085     //    return (double[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
1086     //}
1087     //
1088     //
1089     //public char[] readCharacterArray()
1090     //{
1091     //    return (char[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
1092     //}
1093     //
1094     //
1095     //public <T> T[] readMultiple(Class!(T) clazz)
1096     //{
1097     //    Object val = readObject();
1098     //    if(val is null)
1099     //    {
1100     //        return null;
1101     //    }
1102     //    else if(val.getClass().isArray())
1103     //    {
1104     //        if(clazz.isAssignableFrom(val.getClass().getComponentType()))
1105     //        {
1106     //            return (T[]) val;
1107     //        }
1108     //        else
1109     //        {
1110     //            throw unexpectedType(val, Array.newInstance(clazz, 0).getClass());
1111     //        }
1112     //    }
1113     //    else if(clazz.isAssignableFrom(val.getClass()))
1114     //    {
1115     //        T[] array = (T[]) Array.newInstance(clazz, 1);
1116     //        array[0] = (T) val;
1117     //        return array;
1118     //    }
1119     //    else
1120     //    {
1121     //        throw unexpectedType(val, Array.newInstance(clazz, 0).getClass());
1122     //    }
1123     //}
1124     //
1125     //
1126     //public Object[] readMultiple()
1127     //{
1128     //    Object val = readObject();
1129     //    if(val is null)
1130     //    {
1131     //        return null;
1132     //    }
1133     //    else if(val.getClass().isArray())
1134     //    {
1135     //        return (Object[]) val;
1136     //    }
1137     //    else
1138     //    {
1139     //        Object[] array = (Object[]) Array.newInstance(val.getClass(), 1);
1140     //        array[0] = val;
1141     //        return array;
1142     //    }
1143     //}
1144     //
1145     //
1146     //public byte[] readByteMultiple()
1147     //{
1148     //    return new byte[0];  //TODO.
1149     //}
1150     //
1151     //
1152     //public short[] readShortMultiple()
1153     //{
1154     //    return new short[0];  //TODO.
1155     //}
1156     //
1157     //
1158     //public int[] readIntegerMultiple()
1159     //{
1160     //    return new int[0];  //TODO.
1161     //}
1162     //
1163     //
1164     //public long[] readLongMultiple()
1165     //{
1166     //    return new long[0];  //TODO.
1167     //}
1168     //
1169     //
1170     //public float[] readFloatMultiple()
1171     //{
1172     //    return new float[0];  //TODO.
1173     //}
1174     //
1175     //
1176     //public double[] readDoubleMultiple()
1177     //{
1178     //    return new double[0];  //TODO.
1179     //}
1180     //
1181     //
1182     //public char[] readCharacterMultiple()
1183     //{
1184     //    return new char[0];  //TODO.
1185     //}
1186 
1187 
1188     public Object readObject()
1189     {
1190         //implementationMissing(false);
1191         //return null;
1192         bool arrayType = false;
1193         byte code = _buffer.get(_buffer.position());
1194         switch (code)
1195         {
1196             case EncodingCodes.ARRAY8:
1197                  goto case;
1198             case EncodingCodes.ARRAY32:
1199                 arrayType = true;
1200                 break;
1201             default:
1202                 break;
1203         }
1204 
1205         ITypeConstructor constructor = readConstructor();
1206         if(constructor is null)
1207         {
1208             //throw new DecodeException("Unknown constructor");
1209             logError("Unknown constructor");
1210             return null;
1211         }
1212         return constructor.readValue();
1213       //  return constructor.readValue();
1214         //if (arrayType) {
1215         //    return ((ArrayType.ArrayEncoding)constructor).readValueArray();
1216         //} else {
1217         //    return constructor.readValue();
1218         //}
1219     }
1220 
1221 
1222     public Object readObject(Object defaultValue)
1223     {
1224         Object val = readObject();
1225         return val is null ? defaultValue : val;
1226     }
1227 
1228     void register(V)(PrimitiveType!(V) t)
1229     {
1230         AMQPType!V type = cast(AMQPType!V)t;
1231         if (type is null)
1232         {
1233             logError("register error");
1234         }
1235         //Collection!(PrimitiveTypeEncoding!(V)) encodings = type.getAllEncodings();
1236         Collection!(TypeEncoding!(V)) encodings = type.getAllEncodings();
1237 
1238         foreach(TypeEncoding!(V) ec ; encodings)
1239         {
1240             PrimitiveTypeEncoding!(V) encoding = cast(PrimitiveTypeEncoding!(V))ec;
1241             if (encoding is null)
1242             {
1243                 logError("PrimitiveTypeEncoding error");
1244             }
1245             if (encoding.getEncodingCode() == EncodingCodes.LIST8)
1246             {
1247                 _constructors[(cast(int) EncodingCodes.ARRAY8) & 0xFF ] = encoding;
1248             }
1249             if (encoding.getEncodingCode() == EncodingCodes.LIST32)
1250             {
1251                 _constructors[(cast(int) EncodingCodes.ARRAY32) & 0xFF ] = encoding;
1252             }
1253             _constructors[(cast(int) encoding.getEncodingCode()) & 0xFF ] = encoding;
1254         }
1255 
1256     }
1257 
1258     byte readRawByte()
1259     {
1260         return _buffer.get();
1261     }
1262 
1263     int readRawInt()
1264     {
1265         return _buffer.getInt();
1266     }
1267 
1268     long readRawLong()
1269     {
1270         return _buffer.getLong();
1271     }
1272 
1273     short readRawShort()
1274     {
1275         return _buffer.getShort();
1276     }
1277 
1278     float readRawFloat()
1279     {
1280         return _buffer.getFloat();
1281     }
1282 
1283     double readRawDouble()
1284     {
1285         return _buffer.getDouble();
1286     }
1287 
1288     void readRaw(byte[] data, int offset, int length)
1289     {
1290         _buffer.get(data, offset, length);
1291     }
1292 
1293     V readRaw(V)(TypeDecoder!(V) decoder, int size)
1294     {
1295         V decode = decoder.decode(this, _buffer.slice().limit(size));
1296         _buffer.position(_buffer.position()+size);
1297         return decode;
1298     }
1299 
1300 
1301     public void setByteBuffer(ByteBuffer buffer)
1302     {
1303         _buffer = new ByteBufferReader(buffer);
1304     }
1305 
1306     public ByteBuffer getByteBuffer()
1307     {
1308         return _buffer.byteBuffer();
1309     }
1310 
1311     public void setBuffer(ReadableBuffer buffer)
1312     {
1313         _buffer = buffer;
1314     }
1315 
1316     public ReadableBuffer getBuffer()
1317     {
1318         return _buffer;
1319     }
1320 
1321     //CharsetDecoder getCharsetDecoder()
1322     //{
1323     //    return _charsetDecoder;
1324     //}
1325 
1326     interface TypeDecoder(V)
1327     {
1328         V decode(DecoderImpl decoder, ReadableBuffer buf);
1329     }
1330 
1331     class UnknownDescribedType : DescribedType
1332     {
1333         private Object _descriptor;
1334         private Object _described;
1335 
1336         this(Object descriptor, Object described)
1337         {
1338             _descriptor = descriptor;
1339             _described = described;
1340         }
1341 
1342 
1343         public Object getDescriptor()
1344         {
1345             return _descriptor;
1346         }
1347 
1348 
1349         public Object getDescribed()
1350         {
1351             return _described;
1352         }
1353 
1354 
1355         //
1356         //public bool equals(Object obj)
1357         //{
1358         //
1359         //    return obj instanceof DescribedType
1360         //           && _descriptor is null ? ((DescribedType) obj).getDescriptor() is null
1361         //                                 : _descriptor.equals(((DescribedType) obj).getDescriptor())
1362         //           && _described is null ?  ((DescribedType) obj).getDescribed() is null
1363         //                                 : _described.equals(((DescribedType) obj).getDescribed());
1364         //
1365         //}
1366 
1367     }
1368 
1369 
1370     public int getByteBufferRemaining() {
1371         return _buffer.remaining();
1372     }
1373 }