github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/common/serialization/serialize.go (about) 1 package serialization 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "io" 8 "math" 9 10 "reflect" 11 12 "github.com/sixexorg/magnetic-ring/common" 13 "github.com/sixexorg/magnetic-ring/common/sink" 14 ) 15 16 var ErrRange = errors.New("value out of range") 17 var ErrEof = errors.New("got EOF, can not get the next byte") 18 19 // SerializableData describe the data need be serialized. 20 type SerializableData interface { 21 // Write data to writer 22 Serialize(w io.Writer) error 23 24 // read data to reader 25 Deserialize(r io.Reader) error 26 } 27 28 /* 29 ****************************************************************************** 30 * public func for outside calling 31 ****************************************************************************** 32 * 1. WriteVarUint func, depend on the inpute number's Actual number size, 33 * serialize to bytes. 34 * uint8 => (LittleEndian)num in 1 byte = 1bytes 35 * uint16 => 0xfd(1 byte) + (LittleEndian)num in 2 bytes = 3bytes 36 * uint32 => 0xfe(1 byte) + (LittleEndian)num in 4 bytes = 5bytes 37 * uint64 => 0xff(1 byte) + (LittleEndian)num in 8 bytes = 9bytes 38 * 2. ReadVarUint func, this func will read the first byte to determined 39 * the num length to read.and retrun the uint64 40 * first byte = 0xfd, read the next 2 bytes as uint16 41 * first byte = 0xfe, read the next 4 bytes as uint32 42 * first byte = 0xff, read the next 8 bytes as uint64 43 * other else, read this byte as uint8 44 * 3. WriteVarBytes func, this func will output two item as serialization. 45 * length of bytes (uint8/uint16/uint32/uint64) + bytes 46 * 4. WriteString func, this func will output two item as serialization. 47 * length of string(uint8/uint16/uint32/uint64) + bytes(string) 48 * 5. ReadVarBytes func, this func will first read a uint to identify the 49 * length of bytes, and use it to get the next length's bytes to return. 50 * 6. ReadString func, this func will first read a uint to identify the 51 * length of string, and use it to get the next bytes as a string. 52 * 7. GetVarUintSize func, this func will return the length of a uint when it 53 * serialized by the WriteVarUint func. 54 * 8. ReadBytes func, this func will read the specify lenth's bytes and retun. 55 * 9. ReadUint8,16,32,64 read uint with fixed length 56 * 10.WriteUint8,16,32,64 Write uint with fixed length 57 * 11.ToArray SerializableData to ToArray() func. 58 ****************************************************************************** 59 */ 60 61 func WriteVarUint(writer io.Writer, value uint64) error { 62 var buf [9]byte 63 var len = 0 64 if value < 0xFD { 65 buf[0] = uint8(value) 66 len = 1 67 } else if value <= 0xFFFF { 68 buf[0] = 0xFD 69 binary.LittleEndian.PutUint16(buf[1:], uint16(value)) 70 len = 3 71 } else if value <= 0xFFFFFFFF { 72 buf[0] = 0xFE 73 binary.LittleEndian.PutUint32(buf[1:], uint32(value)) 74 len = 5 75 } else { 76 buf[0] = 0xFF 77 binary.LittleEndian.PutUint64(buf[1:], uint64(value)) 78 len = 9 79 } 80 _, err := writer.Write(buf[:len]) 81 return err 82 } 83 84 func ReadVarUint(reader io.Reader, maxint uint64) (uint64, error) { 85 var res uint64 86 if maxint == 0x00 { 87 maxint = math.MaxUint64 88 } 89 var fb [9]byte 90 _, err := io.ReadFull(reader, fb[:1]) 91 if err != nil { 92 return 0, err 93 } 94 95 if fb[0] == byte(0xfd) { 96 _, err := io.ReadFull(reader, fb[1:3]) 97 if err != nil { 98 return 0, err 99 } 100 res = uint64(binary.LittleEndian.Uint16(fb[1:3])) 101 } else if fb[0] == byte(0xfe) { 102 _, err := io.ReadFull(reader, fb[1:5]) 103 if err != nil { 104 return 0, err 105 } 106 res = uint64(binary.LittleEndian.Uint32(fb[1:5])) 107 } else if fb[0] == byte(0xff) { 108 _, err := io.ReadFull(reader, fb[1:9]) 109 if err != nil { 110 return 0, err 111 } 112 res = uint64(binary.LittleEndian.Uint64(fb[1:9])) 113 } else { 114 res = uint64(fb[0]) 115 } 116 if res > maxint { 117 return 0, ErrRange 118 } 119 return res, nil 120 } 121 122 func WriteVarBytes(writer io.Writer, value []byte) error { 123 err := WriteVarUint(writer, uint64(len(value))) 124 if err != nil { 125 return err 126 } 127 _, err = writer.Write(value) 128 return err 129 } 130 131 func WriteString(writer io.Writer, value string) error { 132 return WriteVarBytes(writer, []byte(value)) 133 } 134 135 func ReadVarBytes(reader io.Reader) ([]byte, error) { 136 val, err := ReadVarUint(reader, 0) 137 if err != nil { 138 return nil, err 139 } 140 str, err := byteXReader(reader, val) 141 if err != nil { 142 return nil, err 143 } 144 return str, nil 145 } 146 147 func ReadString(reader io.Reader) (string, error) { 148 val, err := ReadVarBytes(reader) 149 if err != nil { 150 return "", err 151 } 152 return string(val), nil 153 } 154 155 func ReadComplex(reader io.Reader) (*sink.ComplexType, error) { 156 fb := [2]byte{} 157 _, err := io.ReadFull(reader, fb[:2]) 158 if err != nil { 159 return nil, err 160 } 161 size := common.BytesToUint16(fb[:]) 162 fb2 := [1]byte{} 163 _, err = io.ReadFull(reader, fb2[:]) 164 if err != nil { 165 return nil, err 166 } 167 fb3 := make([]byte, size) 168 _, err = io.ReadFull(reader, fb3[:]) 169 if err != nil { 170 return nil, err 171 } 172 cp := &sink.ComplexType{ 173 Size: fb, 174 MType: fb2[0], 175 Data: fb3[:], 176 } 177 return cp, nil 178 } 179 func GetVarUintSize(value uint64) int { 180 if value < 0xfd { 181 return 1 182 } else if value <= 0xffff { 183 return 3 184 } else if value <= 0xFFFFFFFF { 185 return 5 186 } else { 187 return 9 188 } 189 } 190 191 func ReadBytes(reader io.Reader, length uint64) ([]byte, error) { 192 str, err := byteXReader(reader, length) 193 if err != nil { 194 return nil, err 195 } 196 return str, nil 197 } 198 199 func ReadUint8(reader io.Reader) (uint8, error) { 200 var p [1]byte 201 _, err := io.ReadFull(reader, p[:]) 202 if err != nil { 203 return 0, ErrEof 204 } 205 return uint8(p[0]), nil 206 } 207 208 func ReadUint16(reader io.Reader) (uint16, error) { 209 var p [2]byte 210 _, err := io.ReadFull(reader, p[:]) 211 if err != nil { 212 return 0, ErrEof 213 } 214 return binary.LittleEndian.Uint16(p[:]), nil 215 } 216 217 func ReadUint32(reader io.Reader) (uint32, error) { 218 var p [4]byte 219 _, err := io.ReadFull(reader, p[:]) 220 if err != nil { 221 return 0, ErrEof 222 } 223 return binary.LittleEndian.Uint32(p[:]), nil 224 } 225 226 func ReadUint64(reader io.Reader) (uint64, error) { 227 var p [8]byte 228 _, err := io.ReadFull(reader, p[:]) 229 if err != nil { 230 return 0, ErrEof 231 } 232 return binary.LittleEndian.Uint64(p[:]), nil 233 } 234 235 func WriteUint8(writer io.Writer, val uint8) error { 236 var p [1]byte 237 p[0] = byte(val) 238 _, err := writer.Write(p[:]) 239 return err 240 } 241 242 func WriteUint16(writer io.Writer, val uint16) error { 243 var p [2]byte 244 binary.LittleEndian.PutUint16(p[:], val) 245 _, err := writer.Write(p[:]) 246 return err 247 } 248 249 func WriteUint32(writer io.Writer, val uint32) error { 250 var p [4]byte 251 binary.LittleEndian.PutUint32(p[:], val) 252 _, err := writer.Write(p[:]) 253 return err 254 } 255 256 func WriteUint64(writer io.Writer, val uint64) error { 257 var p [8]byte 258 binary.LittleEndian.PutUint64(p[:], val) 259 _, err := writer.Write(p[:]) 260 return err 261 } 262 263 func ToArray(data SerializableData) []byte { 264 buf := new(bytes.Buffer) 265 data.Serialize(buf) 266 return buf.Bytes() 267 } 268 269 //************************************************************************** 270 //** internal func *** 271 //************************************************************************** 272 //** 2.byteXReader: read x byte and return []byte. 273 //** 3.byteToUint8: change byte -> uint8 and return. 274 //************************************************************************** 275 276 func byteXReader(reader io.Reader, x uint64) ([]byte, error) { 277 if x == 0 { 278 return nil, nil 279 } 280 //fast path to avoid buffer reallocation 281 if x < 2*1024*1024 { 282 p := make([]byte, x) 283 _, err := io.ReadFull(reader, p) 284 if err != nil { 285 return nil, err 286 } 287 return p, nil 288 } 289 290 // normal path to avoid attack 291 limited := io.LimitReader(reader, int64(x)) 292 buf := &bytes.Buffer{} 293 n, _ := buf.ReadFrom(limited) 294 if n == int64(x) { 295 return buf.Bytes(), nil 296 } 297 return nil, ErrEof 298 } 299 300 func WriteBool(writer io.Writer, val bool) error { 301 err := binary.Write(writer, binary.LittleEndian, val) 302 return err 303 } 304 305 func ReadBool(reader io.Reader) (bool, error) { 306 var x bool 307 err := binary.Read(reader, binary.LittleEndian, &x) 308 return x, err 309 } 310 311 func WriteByte(writer io.Writer, val byte) error { 312 _, err := writer.Write([]byte{val}) 313 if err != nil { 314 return err 315 } 316 return nil 317 } 318 319 func ReadByte(reader io.Reader) (byte, error) { 320 b, err := byteXReader(reader, 1) 321 if err != nil { 322 return 0, err 323 } 324 return b[0], nil 325 } 326 func ReadRealase(r io.Reader, typ reflect.Type) (out interface{}, err error) { 327 switch typ { 328 case common.BType_Bool: 329 out, err = ReadBool(r) 330 case common.BType_Uint32: 331 out, err = ReadUint32(r) 332 case common.BType_Uint64: 333 out, err = ReadUint64(r) 334 case common.BType_BigInt: 335 cp := &sink.ComplexType{} 336 cp, err = ReadComplex(r) 337 if err != nil { 338 return nil, err 339 } 340 out, _ = cp.ComplexToBigInt() 341 case common.BType_Hash: 342 var byteArr []byte 343 byteArr, err = ReadBytes(r, common.HashLength) 344 if err != nil { 345 return nil, err 346 } 347 out, err = common.ParseHashFromBytes(byteArr) 348 case common.BType_Address: 349 var addr []byte 350 addr, err = ReadBytes(r, common.AddrLength) 351 if err != nil { 352 return nil, err 353 } 354 out = common.Bytes2Address(addr) 355 case common.BType_Symbol: 356 var symArr []byte 357 symArr, err = ReadBytes(r, common.SymbolLen) 358 if err != nil { 359 return nil, err 360 } 361 out = common.Bytes2Symbol(symArr) 362 case common.BType_TxIns: 363 cp := &sink.ComplexType{} 364 cp, err = ReadComplex(r) 365 if err != nil { 366 return nil, err 367 } 368 out, _ = cp.ComplexToTxIns() 369 case common.BType_TxOuts: 370 cp := &sink.ComplexType{} 371 cp, err = ReadComplex(r) 372 if err != nil { 373 return nil, err 374 } 375 out, _ = cp.ComplexToTxOuts() 376 case common.BType_TxHashArray: 377 cp := &sink.ComplexType{} 378 cp, err = ReadComplex(r) 379 if err != nil { 380 return nil, err 381 } 382 out, _ = cp.ComplexToHashArray() 383 case common.BType_SigBuf: 384 cp := &sink.ComplexType{} 385 cp, err = ReadComplex(r) 386 if err != nil { 387 return nil, err 388 } 389 out, _ = cp.ComplexToSigBuf() 390 case common.BType_Bytes: 391 cp := &sink.ComplexType{} 392 cp, err = ReadComplex(r) 393 if err != nil { 394 return nil, err 395 } 396 out, _ = cp.ComplexToBytes() 397 } 398 return 399 }