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  }