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.impl.MapElement; 13 14 import hunt.proton.codec.impl.AbstractElement; 15 import hunt.proton.codec.impl.Element; 16 import hunt.proton.codec.impl.ArrayElement; 17 import hunt.proton.codec.Data; 18 import hunt.collection.Map; 19 import hunt.io.ByteBuffer; 20 import std.conv; 21 import hunt.collection.HashMap; 22 23 class MapElement : AbstractElement!(Map!(Object,Object)) 24 { 25 private IElement _first; 26 27 this(IElement parent, IElement prev) 28 { 29 super(parent, prev); 30 } 31 32 33 public int count() 34 { 35 int count = 0; 36 IElement elt = _first; 37 while(elt !is null) 38 { 39 count++; 40 elt = elt.next(); 41 } 42 return count; 43 } 44 45 public int size() 46 { 47 int count = 0; 48 int size = 0; 49 IElement elt = _first; 50 while(elt !is null) 51 { 52 count++; 53 size += elt.size(); 54 elt = elt.next(); 55 } 56 if(isElementOfArray()) 57 { 58 ArrayElement parent = cast(ArrayElement) parent(); 59 60 if(parent.constructorType() == ArrayElement.SMALL) 61 { 62 if(count > 255 || size > 254) 63 { 64 parent.setConstructorType(ArrayElement.ConstructorType.LARGE); 65 size += 8; 66 } 67 else 68 { 69 size += 2; 70 } 71 } 72 else 73 { 74 size += 8; 75 } 76 } 77 else 78 { 79 if(count <= 255 && size <= 254) 80 { 81 size += 3; 82 } 83 else 84 { 85 size+=9; 86 } 87 } 88 89 return size; 90 } 91 92 public Object getValue() 93 { 94 Map!(Object,Object) map = new HashMap!(Object,Object); 95 IElement elt = _first; 96 while(elt !is null) 97 { 98 Object key = cast(Object)elt.getValue(); 99 Object value; 100 elt = elt.next(); 101 if(elt !is null) 102 { 103 value = elt.getValue(); 104 elt = elt.next(); 105 } 106 else 107 { 108 value = null; 109 } 110 map.put(key,value); 111 } 112 113 return cast(Object)map; 114 } 115 116 public Data.DataType getDataType() 117 { 118 return Data.DataType.MAP; 119 } 120 121 public int encode(ByteBuffer b) 122 { 123 int encodedSize = size(); 124 125 int count = 0; 126 int size = 0; 127 IElement elt = _first; 128 while(elt !is null) 129 { 130 count++; 131 size += elt.size(); 132 elt = elt.next(); 133 } 134 135 if(encodedSize > b.remaining()) 136 { 137 return 0; 138 } 139 else 140 { 141 if(isElementOfArray()) 142 { 143 switch((cast(ArrayElement)parent()).constructorType()) 144 { 145 case ArrayElement.ConstructorType.SMALL: 146 b.put(cast(byte)(size+1)); 147 b.put(cast(byte)count); 148 break; 149 case ArrayElement.ConstructorType.LARGE: 150 b.putInt((size+4)); 151 b.putInt(count); 152 break; 153 default: 154 break; 155 } 156 } 157 else 158 { 159 if(size <= 254 && count <=255) 160 { 161 b.put(cast(byte)0xc1); 162 b.put(cast(byte)(size+1)); 163 b.put(cast(byte)count); 164 } 165 else 166 { 167 b.put(cast(byte)0xd1); 168 b.putInt((size+4)); 169 b.putInt(count); 170 } 171 172 } 173 174 elt = _first; 175 while(elt !is null) 176 { 177 elt.encode(b); 178 elt = elt.next(); 179 } 180 181 return encodedSize; 182 } 183 } 184 185 public bool canEnter() 186 { 187 return true; 188 } 189 190 public IElement child() 191 { 192 return _first; 193 } 194 195 public void setChild(IElement elt) 196 { 197 _first = elt; 198 } 199 200 public IElement checkChild(IElement element) 201 { 202 return element; 203 } 204 205 public IElement addChild(IElement element) 206 { 207 _first = element; 208 return element; 209 } 210 211 override 212 string startSymbol() { 213 return "{"; 214 } 215 216 override 217 string stopSymbol() { 218 return "}"; 219 } 220 221 }