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 }