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.FastPathDataType; 12 13 import hunt.Exceptions; 14 import hunt.collection.Collection; 15 import hunt.proton.amqp.Binary; 16 import hunt.proton.amqp.Symbol; 17 import hunt.proton.amqp.UnsignedLong; 18 import hunt.proton.amqp.messaging.Data; 19 import hunt.proton.codec.AMQPType; 20 import hunt.proton.codec.Decoder; 21 import hunt.proton.codec.DecoderImpl; 22 import hunt.proton.codec.EncoderImpl; 23 import hunt.proton.codec.EncodingCodes; 24 import hunt.proton.codec.FastPathDescribedTypeConstructor; 25 import hunt.proton.codec.ReadableBuffer; 26 import hunt.proton.codec.TypeEncoding; 27 import hunt.proton.codec.WritableBuffer; 28 import hunt.proton.codec.messaging.DataType; 29 import std.concurrency : initOnce; 30 import hunt.logging; 31 import std.conv : to; 32 33 class FastPathDataType : AMQPType!(Data), FastPathDescribedTypeConstructor!(Data) { 34 35 private static byte DESCRIPTOR_CODE = 0x75; 36 37 //private static Object[] DESCRIPTORS = 38 //{ 39 // UnsignedLong.valueOf(DESCRIPTOR_CODE), Symbol.valueOf("amqp:data:binary"), 40 //}; 41 42 static Object[] DESCRIPTORS() { 43 __gshared Object[] inst; 44 return initOnce!inst([UnsignedLong.valueOf(DESCRIPTOR_CODE), Symbol.valueOf("amqp:data:binary")]); 45 } 46 47 private DataType dataType; 48 49 this(EncoderImpl encoder) { 50 this.dataType = new DataType(encoder); 51 } 52 53 public EncoderImpl getEncoder() { 54 return dataType.getEncoder(); 55 } 56 57 public DecoderImpl getDecoder() { 58 return dataType.getDecoder(); 59 } 60 61 override 62 public bool encodesJavaPrimitive() { 63 return false; 64 } 65 66 override 67 public TypeInfo getTypeClass() { 68 return dataType.getTypeClass(); 69 } 70 71 override 72 public ITypeEncoding getEncoding(Object val) { 73 return dataType.getEncoding(cast(Data)val); 74 } 75 76 override 77 public TypeEncoding!(Data) getCanonicalEncoding() { 78 return dataType.getCanonicalEncoding(); 79 } 80 81 override 82 public Collection!(TypeEncoding!(Data)) getAllEncodings() { 83 return dataType.getAllEncodings(); 84 } 85 86 override 87 public Data readValue() { 88 ReadableBuffer buffer = getDecoder().getBuffer(); 89 byte encodingCode = buffer.get(); 90 91 int size = 0; 92 93 switch (encodingCode) { 94 case EncodingCodes.VBIN8: 95 size = buffer.get() & 0xFF; 96 break; 97 case EncodingCodes.VBIN32: 98 size = buffer.getInt(); 99 break; 100 case EncodingCodes.NULL: 101 return new Data(null); 102 default: 103 { 104 logError("Expected Binary type but found encoding: %d",encodingCode); 105 break; 106 } 107 //throw new ProtonException("Expected Binary type but found encoding: " ~ encodingCode); 108 } 109 110 if (size > buffer.remaining()) { 111 throw new IllegalArgumentException("Binary data size " ~ to!string(size) ~ " is specified to be greater than the " ~ 112 "amount of data available ("~ to!string(buffer.remaining())~")"); 113 } 114 115 byte[] data = new byte[size]; 116 buffer.get(data, 0, size); 117 118 return new Data(new Binary(data)); 119 } 120 121 override 122 public void skipValue() { 123 implementationMissing(false); 124 // getDecoder().readConstructor().skipValue(); 125 } 126 127 override 128 public void write(Object v) { 129 Data data = cast(Data)v; 130 WritableBuffer buffer = getEncoder().getBuffer(); 131 buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR); 132 buffer.put(EncodingCodes.SMALLULONG); 133 buffer.put(DESCRIPTOR_CODE); 134 getEncoder().writeBinary(data.getValue()); 135 } 136 137 public static void register(Decoder decoder, EncoderImpl encoder) { 138 FastPathDataType type = new FastPathDataType(encoder); 139 //implementationMissing(false); 140 foreach(Object descriptor ; DESCRIPTORS) { 141 // decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type); 142 decoder.registerFastPath(descriptor, type); 143 } 144 encoder.register(type); 145 } 146 }