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