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 }