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 }