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.BinaryType;
13 
14 import hunt.proton.codec.SmallFloatingSizePrimitiveTypeEncoding;
15 import hunt.proton.codec.ReadableBuffer;
16 import hunt.proton.codec.TypeEncoding;
17 import hunt.proton.codec.LargeFloatingSizePrimitiveTypeEncoding;
18 import hunt.proton.codec.EncodingCodes;
19 import hunt.proton.codec.AbstractPrimitiveType;
20 import hunt.proton.codec.PrimitiveTypeEncoding;
21 import hunt.collection.Collection;
22 import hunt.proton.codec.EncoderImpl;
23 import hunt.proton.codec.DecoderImpl;
24 import hunt.collection.ArrayList;
25 
26 
27 import hunt.Exceptions;
28 import hunt.proton.amqp.Binary;
29 import hunt.logging;
30 
31 class BinaryType : AbstractPrimitiveType!(Binary)
32 {
33     private BinaryEncoding _binaryEncoding;
34     private BinaryEncoding _shortBinaryEncoding;
35 
36     interface BinaryEncoding : PrimitiveTypeEncoding!(Binary)
37     {
38 
39     }
40 
41     this(EncoderImpl encoder, DecoderImpl decoder)
42     {
43         _binaryEncoding = new LongBinaryEncoding(encoder, decoder);
44         _shortBinaryEncoding = new ShortBinaryEncoding(encoder, decoder);
45         encoder.register(typeid(Binary), this);
46         decoder.register(this);
47     }
48 
49 
50     public TypeInfo getTypeClass()
51     {
52         return typeid(Binary);
53     }
54 
55 
56     public ITypeEncoding getEncoding(Object val)
57     {
58         return (cast(Binary)val).getLength() <= 255 ? _shortBinaryEncoding : _binaryEncoding;
59     }
60 
61 
62     public BinaryEncoding getCanonicalEncoding()
63     {
64         return _binaryEncoding;
65     }
66 
67 
68     public Collection!(TypeEncoding!(Binary)) getAllEncodings()
69     {
70         ArrayList!(TypeEncoding!(Binary)) lst = new ArrayList!(TypeEncoding!(Binary))();
71         lst.add(cast(TypeEncoding!(Binary))_shortBinaryEncoding);
72         lst.add(cast(TypeEncoding!(Binary))_binaryEncoding);
73         //return Arrays.asList(_shortBinaryEncoding, _binaryEncoding);
74         return lst;
75     }
76 
77     //public Collection!(PrimitiveTypeEncoding!(Binary)) getAllEncodings()
78     //{
79     //   return super.getAllEncodings();
80     //}
81 
82 
83     public void fastWrite(EncoderImpl encoder, Binary binary)
84     {
85         if (binary.getLength() <= 255)
86         {
87             // Reserve size of body + type encoding and single byte size
88             encoder.getBuffer().ensureRemaining(2 + binary.getLength());
89             encoder.writeRaw(EncodingCodes.VBIN8);
90             encoder.writeRaw(cast(byte) binary.getLength());
91             encoder.writeRaw(binary.getArray(), binary.getArrayOffset(), binary.getLength());
92         }
93         else
94         {
95             // Reserve size of body + type encoding and four byte size
96             encoder.getBuffer().ensureRemaining(5 + binary.getLength());
97             encoder.writeRaw(EncodingCodes.VBIN32);
98             encoder.writeRaw(binary.getLength());
99             encoder.writeRaw(binary.getArray(), binary.getArrayOffset(), binary.getLength());
100         }
101     }
102 
103     class LongBinaryEncoding
104             : LargeFloatingSizePrimitiveTypeEncoding!(Binary)
105             , BinaryEncoding
106     {
107 
108         this(EncoderImpl encoder, DecoderImpl decoder)
109         {
110             super(encoder, decoder);
111         }
112 
113         override
114         protected void writeEncodedValue(Binary val)
115         {
116             getEncoder().getBuffer().ensureRemaining(val.getLength());
117             getEncoder().writeRaw(val.getArray(), val.getArrayOffset(), val.getLength());
118         }
119 
120         override
121         protected int getEncodedValueSize(Binary val)
122         {
123             return val.getLength();
124         }
125 
126         override
127         public byte getEncodingCode()
128         {
129             return EncodingCodes.VBIN32;
130         }
131 
132         override
133         public BinaryType getType()
134         {
135             return this.outer;
136         }
137 
138         override
139         public bool encodesSuperset(TypeEncoding!(Binary) encoding)
140         {
141             return (getType() == encoding.getType());
142         }
143 
144         override
145         public Object readValue()
146         {
147             DecoderImpl decoder = getDecoder();
148             int size = decoder.readRawInt();
149             if (size > decoder.getByteBufferRemaining()) {
150                 logError("Binary data size is specified to be greater than the amount of data available");
151                 //throw new IllegalArgumentException("Binary data size "+size+" is specified to be greater than the amount of data available ("+
152                 //                                   decoder.getByteBufferRemaining()+")");
153             }
154             byte[] data = new byte[size];
155             decoder.readRaw(data, 0, size);
156             return new Binary(data);
157         }
158 
159         override
160         public void skipValue()
161         {
162             DecoderImpl decoder = getDecoder();
163             ReadableBuffer buffer = decoder.getBuffer();
164             int size = decoder.readRawInt();
165             buffer.position(buffer.position() + size);
166         }
167 
168 
169         override
170         public TypeInfo getTypeClass()
171         {
172             return super.getTypeClass();
173         }
174 
175 
176 
177         override
178         public bool encodesJavaPrimitive()
179         {
180             return false;
181         }
182 
183 
184         override void writeConstructor()
185         {
186             super.writeConstructor();
187         }
188 
189         override int getConstructorSize()
190         {
191             return super.getConstructorSize();
192         }
193 
194     }
195 
196     class ShortBinaryEncoding
197             : SmallFloatingSizePrimitiveTypeEncoding!(Binary)
198             , BinaryEncoding
199     {
200 
201         this(EncoderImpl encoder, DecoderImpl decoder)
202         {
203             super(encoder, decoder);
204         }
205 
206         override
207         protected void writeEncodedValue(Binary val)
208         {
209             getEncoder().getBuffer().ensureRemaining(val.getLength());
210             getEncoder().writeRaw(val.getArray(), val.getArrayOffset(), val.getLength());
211         }
212 
213         override
214         protected int getEncodedValueSize(Binary val)
215         {
216             return val.getLength();
217         }
218 
219         override
220         public byte getEncodingCode()
221         {
222             return EncodingCodes.VBIN8;
223         }
224 
225         override
226         public BinaryType getType()
227         {
228             return this.outer;
229         }
230 
231         override
232         public bool encodesSuperset(TypeEncoding!(Binary) encoder)
233         {
234             return encoder == this;
235         }
236 
237         override
238         public Binary readValue()
239         {
240             int size = (cast(int)getDecoder().readRawByte()) & 0xff;
241             byte[] data = new byte[size];
242             getDecoder().readRaw(data, 0, size);
243             return new Binary(data);
244         }
245 
246         override
247         public void skipValue()
248         {
249             DecoderImpl decoder = getDecoder();
250             ReadableBuffer buffer = decoder.getBuffer();
251             int size = (cast(int)getDecoder().readRawByte()) & 0xff;
252             buffer.position(buffer.position() + size);
253         }
254 
255 
256         override
257         public TypeInfo getTypeClass()
258         {
259             return super.getTypeClass();
260         }
261 
262 
263         override
264         public bool encodesJavaPrimitive()
265         {
266             return false;
267         }
268 
269         override void writeConstructor()
270         {
271             super.writeConstructor();
272         }
273 
274         override int getConstructorSize()
275         {
276             return super.getConstructorSize();
277         }
278     }
279 }