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 module hunt.proton.codec.messaging.FastPathDeliveryAnnotationsType;
12 
13 import hunt.collection.Collection;
14 import hunt.collection.LinkedHashMap;
15 import hunt.collection.Map;
16 
17 import hunt.proton.amqp.Symbol;
18 import hunt.proton.amqp.UnsignedLong;
19 import hunt.proton.amqp.messaging.DeliveryAnnotations;
20 import hunt.proton.codec.AMQPType;
21 import hunt.proton.codec.ArrayType;
22 import hunt.proton.codec.DecodeException;
23 import hunt.proton.codec.Decoder;
24 import hunt.proton.codec.DecoderImpl;
25 import hunt.proton.codec.EncoderImpl;
26 import hunt.proton.codec.EncodingCodes;
27 import hunt.proton.codec.FastPathDescribedTypeConstructor;
28 import hunt.proton.codec.MapType;
29 import hunt.proton.codec.PrimitiveTypeEncoding;
30 import hunt.proton.codec.ReadableBuffer;
31 import hunt.proton.codec.SymbolType;
32 import hunt.proton.codec.TypeConstructor;
33 import hunt.proton.codec.TypeEncoding;
34 import hunt.proton.codec.WritableBuffer;
35 import hunt.proton.codec.messaging.DeliveryAnnotationsType;
36 import std.concurrency : initOnce;
37 import hunt.Exceptions;
38 
39 
40 class FastPathDeliveryAnnotationsType : AMQPType!(DeliveryAnnotations), FastPathDescribedTypeConstructor!(DeliveryAnnotations) {
41 
42     private static byte DESCRIPTOR_CODE = 0x71;
43 
44     //private static Object[] DESCRIPTORS = {
45     //    UnsignedLong.valueOf(DESCRIPTOR_CODE), Symbol.valueOf("amqp:delivery-annotations:map"),
46     //};
47 
48 
49     static Object[]  DESCRIPTORS() {
50         __gshared Object[]  inst;
51         return initOnce!inst([UnsignedLong.valueOf(DESCRIPTOR_CODE), Symbol.valueOf("amqp:delivery-annotations:map")]);
52     }
53 
54     private DeliveryAnnotationsType annotationsType;
55     private SymbolType symbolType;
56 
57     this(EncoderImpl encoder) {
58         this.annotationsType = new DeliveryAnnotationsType(encoder);
59         this.symbolType = cast(SymbolType) encoder.getTypeFromClass(typeid(Symbol));
60     }
61 
62     public EncoderImpl getEncoder() {
63         return annotationsType.getEncoder();
64     }
65 
66     public DecoderImpl getDecoder() {
67         return annotationsType.getDecoder();
68     }
69 
70     override
71     public bool encodesJavaPrimitive() {
72         return false;
73     }
74 
75     override
76     public TypeInfo getTypeClass() {
77         return typeid(DeliveryAnnotations);
78     }
79 
80     override
81     public ITypeEncoding getEncoding(Object val) {
82         return annotationsType.getEncoding(cast(DeliveryAnnotations)val);
83     }
84 
85     override
86     public TypeEncoding!(DeliveryAnnotations) getCanonicalEncoding() {
87         return annotationsType.getCanonicalEncoding();
88     }
89 
90     override
91     public  Collection!(TypeEncoding!(DeliveryAnnotations)) getAllEncodings() {
92         return annotationsType.getAllEncodings();
93     }
94 
95     override
96     public DeliveryAnnotations readValue() {
97         implementationMissing(false);
98         return null;
99         //DecoderImpl decoder = getDecoder();
100         //ReadableBuffer buffer = decoder.getBuffer();
101         //
102         //int size;
103         //int count;
104         //
105         //byte encodingCode = buffer.get();
106         //
107         //switch (encodingCode) {
108         //    case EncodingCodes.MAP8:
109         //        size = buffer.get() & 0xFF;
110         //        count = buffer.get() & 0xFF;
111         //        break;
112         //    case EncodingCodes.MAP32:
113         //        size = buffer.getInt();
114         //        count = buffer.getInt();
115         //        break;
116         //    case EncodingCodes.NULL:
117         //        return new DeliveryAnnotations(null);
118         //    default:
119         //        throw new ProtonException("Expected Map type but found encoding: " ~ encodingCode);
120         //}
121         //
122         //if (count > buffer.remaining()) {
123         //    throw new IllegalArgumentException("Map element count " ~ count ~ " is specified to be greater than the " ~
124         //                                       "amount of data available (" ~ buffer.remaining() ~ ")");
125         //}
126         //
127         //TypeConstructor<?> valueConstructor = null;
128         //
129         //Map!(Symbol, Object) map = new LinkedHashMap<>(count);
130         //for(int i = 0; i < count / 2; i++) {
131         //    Symbol key = decoder.readSymbol(null);
132         //    if (key is null) {
133         //        throw new DecodeException("String key in DeliveryAnnotations cannot be null");
134         //    }
135         //
136         //    bool arrayType = false;
137         //    byte code = buffer.get(buffer.position());
138         //    switch (code)
139         //    {
140         //        case EncodingCodes.ARRAY8:
141         //        case EncodingCodes.ARRAY32:
142         //            arrayType = true;
143         //    }
144         //
145         //    valueConstructor = findNextDecoder(decoder, buffer, valueConstructor);
146         //
147         //    Object value;
148         //
149         //    if (arrayType) {
150         //        value = ((ArrayType.ArrayEncoding) valueConstructor).readValueArray();
151         //    } else {
152         //        value = valueConstructor.readValue();
153         //    }
154         //
155         //    map.put(key, value);
156         //}
157         //
158         //return new DeliveryAnnotations(map);
159     }
160 
161     override
162     public void skipValue() {
163         implementationMissing(false);
164       //  getDecoder().readConstructor().skipValue();
165     }
166 
167     override
168     public void write(Object v) {
169         DeliveryAnnotations val = cast(DeliveryAnnotations)v;
170         implementationMissing(false);
171         //WritableBuffer buffer = getEncoder().getBuffer();
172         //
173         //buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
174         //buffer.put(EncodingCodes.SMALLULONG);
175         //buffer.put(DESCRIPTOR_CODE);
176         //
177         //MapType mapType = (MapType) getEncoder().getType(val.getValue());
178         //
179         //mapType.setKeyEncoding(symbolType);
180         //try {
181         //    mapType.write(val.getValue());
182         //} finally {
183         //    mapType.setKeyEncoding(null);
184         //}
185     }
186 
187     public static void register(Decoder decoder, EncoderImpl encoder) {
188         FastPathDeliveryAnnotationsType type = new FastPathDeliveryAnnotationsType(encoder);
189         //implementationMissing(false);
190         foreach(Object descriptor ; DESCRIPTORS) {
191             decoder.registerFastPath(descriptor, type);
192         }
193         encoder.register(type);
194     }
195 
196     //private static TypeConstructor<?> findNextDecoder(DecoderImpl decoder, ReadableBuffer buffer, TypeConstructor<?> previousConstructor) {
197     //    if (previousConstructor is null) {
198     //        return decoder.readConstructor();
199     //    } else {
200     //        byte encodingCode = buffer.get(buffer.position());
201     //        if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(previousConstructor instanceof PrimitiveTypeEncoding<?>)) {
202     //            previousConstructor = decoder.readConstructor();
203     //        } else {
204     //            PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) previousConstructor;
205     //            if (encodingCode != primitiveConstructor.getEncodingCode()) {
206     //                previousConstructor = decoder.readConstructor();
207     //            } else {
208     //                // consume the encoding code byte for real
209     //                encodingCode = buffer.get();
210     //            }
211     //        }
212     //    }
213     //
214     //    if (previousConstructor is null) {
215     //        throw new DecodeException("Unknown constructor found in Map encoding: ");
216     //    }
217     //
218     //    return previousConstructor;
219     //}
220 }