1 module yu.tools.serialize.write;
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 
14 struct WriteStream
15 {
16     @disable this();
17     @disable this(this);
18 
19 	this(IWriteBuffer buffer)
20 	{
21 		_buffer = buffer;
22 	}
23 
24 	~this()
25 	{
26 		StatusNode * node = _status.pop();
27         while(node){
28             yDel(node);
29             node = _status.pop();
30         }
31 	}
32 
33     @property buffer(){return _buffer;}
34 
35 	void write(X)(X value) if(isBasicSupport!(X).isNum)
36 	{
37 		doIsArray(dtTypes!X);
38 		ubyte[X.sizeof] data = nativeToBigEndian!X(value);
39 		append(data);
40 	}
41 
42 	void write(X)(X value) if(isBasicSupport!(X).isChar)
43 	{
44 		doIsArray(dtTypes!X);
45 		append(cast(ubyte)value);
46 	}
47 
48 	void write(X:bool)(X value) 
49 	{
50 		doIsArray(dtTypes!X);
51 		ubyte a = value ? 0x01 : 0x00;
52 		append(a);
53 	}
54 
55 	void write(X:DateTime)(ref X value) 
56 	{
57 		doIsArray(dtTypes!X);
58 		ubyte[2] data;
59 		data = nativeToBigEndian!short(value.year());
60 		append(data);
61 		append(value.month());
62 		append(value.day());
63 		append(value.hour());
64 		append(value.minute());
65 		append(value.second());
66 	}
67 
68 	void write(X:Date)(ref X value) 
69 	{
70 		doIsArray(dtTypes!X);
71 		ubyte[2] data;
72 		data = nativeToBigEndian!short(value.year());
73 		append(data);
74 		append(value.month());
75 		append(value.day());
76 	}
77 
78 	void write(X:Time)(ref X value) 
79 	{
80 		doIsArray(dtTypes!X);
81 		append(value.hour);
82 		append(value.minute);
83 		append(value.second);
84 		ubyte[2] data;
85 		data = nativeToBigEndian!ushort(value.msecond);
86 		append(data);
87 	}
88 
89 
90 	void write(X:char[])(ref X value)
91 	{
92 		writeRawArray(Types.Char,cast(ubyte[])value);
93 	}
94 
95 	void write(X:byte[])(ref X value)
96 	{
97 		writeRawArray(Types.Byte,cast(ubyte[])value);
98 	}
99 
100 	void write(X:ubyte[])(ref X value)
101 	{
102 		writeRawArray(Types.UByte,value);
103 	}
104 
105 	void write(X: string)(ref X value)
106 	{
107 		writeRawArray(Types.Char,cast(ubyte[])value);
108 	}
109 
110 	void write(X)(ref X value) if(isArray!(X) && isBasicSupport!(X).isBSupport && !isStruct!X)
111 	{
112 		startArray!(ForeachType!X)();
113 		scope(success)endArray();
114 		foreach(ref v ; value)
115 		{
116 			write(v);
117 		}
118 	}
119 
120 	void startArray(X)() if(isBasicSupport!(X).isBSupport)
121 	{
122 		Types ty = dtTypes!X;
123 		StatusNode * state = yNew!StatusNode();
124 		state.state = Status.InArray;
125 		state.type = ty;
126 		_status.push(state);
127 		append(Types.Array);
128 		append(ty);
129 		state.begin = _buffer.length;
130 		ubyte[4] data;
131 		append(data);
132 	}
133 
134 	void endArray()
135 	{
136 		StatusNode * state = _status.pop();
137 		if(state is null || state.state != Status.InArray)
138 			throw new WriteException("not in Array!!!");
139 
140 		scope(exit)yDel(state);
141 		ubyte[4] data = nativeToBigEndian!uint(state.len);
142 		//_data[state.begin..(state.begin + 4)] = data; //写入数组长度
143 		_buffer.set(state.begin, data[]);
144 		//append(data[]);
145 		append(Types.End);
146 
147 		StatusNode * state2 = _status.front();
148 		if(state2 !is null && state2.state == Status.InArray)
149 		{
150 			if(state2.type == Types.Array) {
151 				state2.len ++;
152 			}
153 		}
154 	}
155 
156 	void startStruct()
157 	{
158 		StatusNode * state = yNew!StatusNode();
159 		state.state = Status.InStruct;
160 		state.type = Types.Struct;
161 		_status.push(state);
162 		append(Types.Struct);
163 	}
164 
165 	void endStruct()
166 	{
167 		StatusNode * state = _status.pop();
168 
169 		if(state is null || state.state != Status.InStruct)
170 			throw new WriteException("not in struct!!!");
171 		scope(exit)yDel(state);
172 		append(Types.End);
173 		StatusNode * state2 = _status.front();
174 		if(state2 !is null && state2.state == Status.InArray)
175 		{
176 			if(state2.type == Types.Struct) {
177 				state2.len ++;
178 			}
179 		}
180 	}
181 
182 	pragma(inline) void append(ubyte value)
183 	{
184         ubyte * ptr = &value;
185 		_buffer.write(ptr[0..1]);
186 	}
187 
188 	pragma(inline) void append(in ubyte[] value)
189 	{
190 		_buffer.write(value);
191 	}
192 
193 private:
194 	//pragma(inline, true) 
195 	void writeRawArray(Types ty, ubyte[] data)
196 	{
197 		append(Types.Array);
198 		append(ty);
199 		uint leng = cast(uint)data.length;
200 		ubyte[4] dt = nativeToBigEndian!uint(leng);
201 		append(dt[]);
202 		
203 		append(data);
204 		append(Types.End);
205 	}
206 
207 	//pragma(inline, true) 
208 	void doIsArray(Types ty)
209 	{
210 		StatusNode * state = _status.front();
211 		if(state !is null && state.state == Status.InArray)
212 		{
213 			if(state.type == ty) {
214 				state.len ++;
215 			}else {
216 				endArray();
217 				append(ty);
218 			}
219 		}else{
220 			append(ty);
221 		}
222 	}
223 
224 private:
225     IWriteBuffer _buffer;
226 	StatusStack _status;
227 }