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.DynamicDescribedType; 13 14 import hunt.proton.amqp.DescribedType; 15 16 import hunt.collection.Collection; 17 import hunt.collection.Collections; 18 import hunt.collection.HashMap; 19 import hunt.collection.Map; 20 import hunt.proton.codec.AMQPType; 21 22 import hunt.proton.codec.TypeEncoding; 23 import hunt.proton.codec.EncoderImpl; 24 import hunt.collection.List; 25 import hunt.collection.ArrayList; 26 import hunt.proton.codec.EncodingCodes; 27 28 class DynamicDescribedType : AMQPType!(DescribedType) 29 { 30 31 private EncoderImpl _encoder; 32 private Map!(ITypeEncoding, ITypeEncoding) _encodings ;//= new HashMap!(ITypeEncoding, ITypeEncoding)(); 33 private Object _descriptor; 34 35 this(EncoderImpl encoder, Object descriptor) 36 { 37 _encoder = encoder; 38 _descriptor = descriptor; 39 _encodings = new HashMap!(ITypeEncoding, ITypeEncoding); 40 } 41 42 43 public TypeInfo getTypeClass() 44 { 45 return typeid(DescribedType); 46 } 47 48 public ITypeEncoding getEncoding(Object v) 49 { 50 DescribedType val = cast(DescribedType)v; 51 ITypeEncoding underlyingEncoding = _encoder.getType(val.getDescribed()).getEncoding(val.getDescribed()); 52 ITypeEncoding encoding = _encodings.get(underlyingEncoding); 53 if(encoding is null) 54 { 55 encoding = new DynamicDescribedTypeEncoding(underlyingEncoding); 56 _encodings.put(underlyingEncoding, encoding); 57 } 58 59 return encoding; 60 } 61 62 public TypeEncoding!(DescribedType) getCanonicalEncoding() 63 { 64 return null; 65 } 66 67 public Collection!(TypeEncoding!(DescribedType)) getAllEncodings() 68 { 69 //Collection values = _encodings.values(); 70 List!(TypeEncoding!(DescribedType)) lst = new ArrayList!(TypeEncoding!(DescribedType)); 71 foreach(ITypeEncoding v ; _encodings.values() ) 72 { 73 lst.add(cast(TypeEncoding!(DescribedType))v); 74 } 75 //Collection unmodifiable = Collections.unmodifiableCollection(values); 76 return lst; 77 } 78 79 public void write(Object val) 80 { 81 ITypeEncoding encoding = getEncoding(val); 82 encoding.writeConstructor(); 83 encoding.writeValue(val); 84 } 85 86 class DynamicDescribedTypeEncoding : ITypeEncoding 87 { 88 private ITypeEncoding _underlyingEncoding; 89 private ITypeEncoding _descriptorType; 90 private int _constructorSize; 91 92 93 this(ITypeEncoding underlyingEncoding) 94 { 95 _underlyingEncoding = underlyingEncoding; 96 _descriptorType = _encoder.getType(_descriptor).getEncoding(_descriptor); 97 _constructorSize = 1 + _descriptorType.getConstructorSize() 98 + _descriptorType.getValueSize(_descriptor) 99 + _underlyingEncoding.getConstructorSize(); 100 } 101 102 public AMQPType!(DescribedType) getType() 103 { 104 return this.outer; 105 } 106 107 public void writeConstructor() 108 { 109 _encoder.writeRaw(EncodingCodes.DESCRIBED_TYPE_INDICATOR); 110 _descriptorType.writeConstructor(); 111 _descriptorType.writeValue(_descriptor); 112 _underlyingEncoding.writeConstructor(); 113 } 114 115 public int getConstructorSize() 116 { 117 return _constructorSize; 118 } 119 120 public void writeValue(Object val) 121 { 122 _underlyingEncoding.writeValue((cast(DescribedType)val).getDescribed()); 123 } 124 125 public int getValueSize(Object val) 126 { 127 return _underlyingEncoding.getValueSize((cast(DescribedType) val).getDescribed()); 128 } 129 130 public bool isFixedSizeVal() 131 { 132 return _underlyingEncoding.isFixedSizeVal(); 133 } 134 135 public bool encodesSuperset(TypeEncoding!DescribedType encoding) 136 { 137 return (getType() == encoding.getType()); 138 } 139 140 override 141 public bool encodesJavaPrimitive() 142 { 143 return false; 144 } 145 146 int opCmp(ITypeEncoding o) 147 { 148 return this.getConstructorSize - o.getConstructorSize; 149 } 150 151 } 152 }