1 module yu.tools.serialize.read; 2 3 import std.bitmanip; 4 5 import yu.tools.serialize.types; 6 import yu.tools.serialize.status; 7 import yu.tools.serialize.exception; 8 9 import yu.traits; 10 import yu.tools.buffer; 11 import yu.memory.allocator; 12 13 struct ReadStream 14 { 15 @disable this(); 16 @disable this(this); 17 18 this(const(ubyte)[] data) 19 { 20 _data = data; 21 } 22 23 ~this() 24 { 25 StatusNode * node = _status.pop(); 26 while(node){ 27 yDel(node); 28 node = _status.pop(); 29 } 30 } 31 32 Types nextType() 33 { 34 return cast(Types)(_data[_currt]); 35 } 36 37 Types arrayType() 38 { 39 myAssert(_data[_currt] == Types.Array, "check Array type erro"); 40 return cast(Types)(_data[_currt + 1]); 41 } 42 43 // return len. 44 uint startReadArray() 45 { 46 myAssert(_data[_currt] == Types.Array,"check Array type erro"); 47 StatusNode * state = yNew!StatusNode(); 48 state.state = Status.InArray; 49 state.type = cast(Types)_data[_currt+1]; 50 _status.push(state); 51 52 _currt += 2; 53 size_t start = _currt; 54 _currt += 4; 55 ubyte[4] data; 56 data[] = _data[start.._currt]; 57 return bigEndianToNative!(uint,uint.sizeof)(data); 58 } 59 60 void endReadArray() 61 { 62 auto node = _status.front(); 63 if(node is null || node.state != Status.InArray) 64 throw new ReadException("Not in A array!"); 65 _currt ++; 66 _status.pop(); 67 yDel(node); 68 } 69 70 void startReadStruct() 71 { 72 myAssert(_data[_currt] == Types.Struct,"check struct type erro"); 73 _currt ++; 74 75 StatusNode * state = yNew!StatusNode(); 76 state.state = Status.InStruct; 77 state.type = Types.Struct; 78 _status.push(state); 79 } 80 81 void endReadStruct() // TODO: read to end 82 { 83 auto node = _status.front(); 84 if(node is null || node.state != Status.InStruct) 85 throw new ReadException("Not in A Struct!"); 86 while(nextType() != Types.End){ 87 skipType(); 88 } 89 _currt ++; 90 _status.pop(); 91 yDel(node); 92 } 93 94 auto read(X)() if(isBasicSupport!(X).isNum) 95 { 96 typePrev(dtTypes!X); 97 size_t start = _currt; 98 _currt += X.sizeof; 99 ubyte[X.sizeof] data = _data[start.._currt]; 100 return bigEndianToNative!(X,X.sizeof)(data); 101 } 102 103 auto read(X)() if(isBasicSupport!(X).isChar) 104 { 105 typePrev(dtTypes!X); 106 X v = _data[_currt]; 107 ++_currt; 108 return v; 109 } 110 111 bool read(X:bool)() 112 { 113 typePrev(dtTypes!X); 114 ubyte v = _data[_currt]; 115 ++_currt; 116 return v > 0; 117 } 118 119 DateTime read(X:DateTime)() 120 { 121 typePrev(dtTypes!X); 122 DateTime dt; 123 size_t start = _currt; 124 _currt += 2; 125 ubyte[2] data = _data[start.._currt]; 126 dt.year(bigEndianToNative!(short)(data)); 127 dt.month(cast(Month)(_data[_currt])); 128 ++_currt; 129 dt.day(_data[_currt]); 130 ++_currt; 131 132 dt.hour(_data[_currt]); 133 ++_currt; 134 dt.minute(_data[_currt]); 135 ++_currt; 136 dt.second(_data[_currt]); 137 ++_currt; 138 139 return dt; 140 } 141 142 Date read(X:Date)() 143 { 144 typePrev(dtTypes!X); 145 Date dt; 146 size_t start = _currt; 147 _currt += 2; 148 ubyte[2] data = _data[start.._currt]; 149 dt.year(bigEndianToNative!(short)(data)); 150 dt.month(cast(Month)(_data[_currt])); 151 ++_currt; 152 dt.day(_data[_currt]); 153 ++_currt; 154 155 return dt; 156 } 157 158 Time read(X:Time)() 159 { 160 typePrev(dtTypes!X); 161 Time tm; 162 tm.hour = _data[_currt]; 163 ++_currt; 164 tm.minute = _data[_currt]; 165 ++_currt; 166 tm.second = _data[_currt]; 167 ++_currt; 168 169 size_t start = _currt; 170 _currt += 2; 171 ubyte[2] data = _data[start.._currt]; 172 tm.msecond = bigEndianToNative!(ushort)(data); 173 174 return tm; 175 } 176 177 ubyte[] read(X:ubyte[])() 178 { 179 myAssert(Types.Array == _data[_currt], "read check type erro : " ~ X.stringof); 180 myAssert(Types.UByte == _data[_currt + 1] , "read check type erro : " ~ X.stringof); 181 182 uint len = startReadArray(); 183 size_t start = _currt; 184 _currt += len; 185 auto data = _data[start.._currt]; 186 endReadArray(); 187 return cast(ubyte[])data; 188 } 189 190 string read(X: string)() 191 { 192 myAssert(Types.Array == _data[_currt],"read check type erro : " ~ X.stringof); 193 myAssert(Types.Char == _data[_currt + 1],"read check type erro : " ~ X.stringof); 194 195 uint len = startReadArray(); 196 size_t start = _currt; 197 _currt += len; 198 auto data = _data[start.._currt]; 199 endReadArray(); 200 return cast(string)data; 201 } 202 203 private: 204 void typePrev(Types ty) 205 { 206 StatusNode * state2 = _status.front(); 207 if(state2 is null) 208 { 209 myAssert(ty == _data[_currt],"read check type erro " ); 210 ++_currt; 211 } 212 else if(state2.state != Status.InArray) 213 { 214 myAssert(ty == _data[_currt],"read check type erro " ); 215 ++_currt; 216 } 217 else 218 { 219 myAssert(ty == state2.type,"read check type erro " ); 220 } 221 } 222 223 void skipType() 224 { 225 Types type = nextType(); 226 switch(type) with(Types){ 227 case Char: 228 case UChar: 229 case Bool: 230 _currt += 2; 231 break; 232 case Short: 233 case UShort: 234 _currt += 3; 235 break; 236 case Int: 237 case UInt: 238 case Float: 239 case Date: 240 _currt += 5; 241 break; 242 case Time: 243 _currt += 6; 244 break; 245 case DateTime: 246 _currt += 8; 247 break; 248 case Long: 249 case ULong: 250 case Double: 251 _currt += 9; 252 break; 253 case Array: 254 skipArray(); 255 break; 256 case Struct: 257 skipStruct(); 258 break; 259 default: 260 throw new ReadException("Read in Array type Error"); 261 } 262 } 263 264 void skipArray() 265 { 266 Types type = arrayType(); 267 uint len = startReadArray(); 268 switch(type) with(Types){ 269 case Char: 270 case UChar: 271 case Bool: 272 _currt += len; 273 break; 274 case Short: 275 case UShort: 276 _currt += (len * 2); 277 break; 278 case Int: 279 case UInt: 280 case Float: 281 case Date: 282 _currt += (len * 4); 283 break; 284 case Time: 285 _currt += (len * 5); 286 break; 287 case DateTime: 288 _currt += (len * 7); 289 break; 290 case Long: 291 case ULong: 292 case Double: 293 _currt += (len * 8); 294 break; 295 case Array: 296 foreach(i; 0..len){ 297 skipArray(); 298 } 299 break; 300 case Struct: 301 foreach(i; 0..len){ 302 skipStruct(); 303 } 304 break; 305 default: 306 throw new ReadException("Read in Array type Error"); 307 } 308 endReadArray(); 309 } 310 311 void skipStruct() 312 { 313 startReadStruct(); 314 endReadStruct(); 315 } 316 private: 317 const(ubyte)[] _data; 318 size_t _currt; 319 320 StatusStack _status; 321 } 322 323 private: 324 pragma(inline) 325 void myAssert(string file = __FILE__, int line = __LINE__)(bool erro, lazy string msg = string.init) 326 { 327 if(!erro) 328 throw new ReadException(msg,file,line); 329 }