github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/common/sink/serialize.go (about)

     1  package sink
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"io"
     8  	"math"
     9  )
    10  
    11  var ErrRange = errors.New("value out of range")
    12  var ErrEof = errors.New("got EOF, can not get the next byte")
    13  
    14  // SerializableData describe the data need be serialized.
    15  type SerializableData interface {
    16  	// Write data to writer
    17  	Serialize(w io.Writer) error
    18  
    19  	// read data to reader
    20  	Deserialize(r io.Reader) error
    21  }
    22  
    23  /*
    24   ******************************************************************************
    25   * public func for outside calling
    26   ******************************************************************************
    27   * 1. WriteVarUint func, depend on the inpute number's Actual number size,
    28   *    serialize to bytes.
    29   *      uint8  =>  (LittleEndian)num in 1 byte                 = 1bytes
    30   *      uint16 =>  0xfd(1 byte) + (LittleEndian)num in 2 bytes = 3bytes
    31   *      uint32 =>  0xfe(1 byte) + (LittleEndian)num in 4 bytes = 5bytes
    32   *      uint64 =>  0xff(1 byte) + (LittleEndian)num in 8 bytes = 9bytes
    33   * 2. ReadVarUint  func, this func will read the first byte to determined
    34   *    the num length to read.and retrun the uint64
    35   *      first byte = 0xfd, read the next 2 bytes as uint16
    36   *      first byte = 0xfe, read the next 4 bytes as uint32
    37   *      first byte = 0xff, read the next 8 bytes as uint64
    38   *      other else,        read this byte as uint8
    39   * 3. WriteVarBytes func, this func will output two item as serialization.
    40   *      length of bytes (uint8/uint16/uint32/uint64)  +  bytes
    41   * 4. WriteString func, this func will output two item as serialization.
    42   *      length of string(uint8/uint16/uint32/uint64)  +  bytes(string)
    43   * 5. ReadVarBytes func, this func will first read a uint to identify the
    44   *    length of bytes, and use it to get the next length's bytes to return.
    45   * 6. ReadString func, this func will first read a uint to identify the
    46   *    length of string, and use it to get the next bytes as a string.
    47   * 7. GetVarUintSize func, this func will return the length of a uint when it
    48   *    serialized by the WriteVarUint func.
    49   * 8. ReadBytes func, this func will read the specify lenth's bytes and retun.
    50   * 9. ReadUint8,16,32,64 read uint with fixed length
    51   * 10.WriteUint8,16,32,64 Write uint with fixed length
    52   * 11.ToArray SerializableData to ToArray() func.
    53   ******************************************************************************
    54   */
    55  
    56  func WriteVarUint(writer io.Writer, value uint64) error {
    57  	var buf [9]byte
    58  	var len = 0
    59  	if value < 0xFD {
    60  		buf[0] = uint8(value)
    61  		len = 1
    62  	} else if value <= 0xFFFF {
    63  		buf[0] = 0xFD
    64  		binary.LittleEndian.PutUint16(buf[1:], uint16(value))
    65  		len = 3
    66  	} else if value <= 0xFFFFFFFF {
    67  		buf[0] = 0xFE
    68  		binary.LittleEndian.PutUint32(buf[1:], uint32(value))
    69  		len = 5
    70  	} else {
    71  		buf[0] = 0xFF
    72  		binary.LittleEndian.PutUint64(buf[1:], uint64(value))
    73  		len = 9
    74  	}
    75  	_, err := writer.Write(buf[:len])
    76  	return err
    77  }
    78  
    79  func ReadVarUint(reader io.Reader, maxint uint64) (uint64, error) {
    80  	var res uint64
    81  	if maxint == 0x00 {
    82  		maxint = math.MaxUint64
    83  	}
    84  	var fb [9]byte
    85  	_, err := io.ReadFull(reader, fb[:1])
    86  	if err != nil {
    87  		return 0, err
    88  	}
    89  
    90  	if fb[0] == byte(0xfd) {
    91  		_, err := io.ReadFull(reader, fb[1:3])
    92  		if err != nil {
    93  			return 0, err
    94  		}
    95  		res = uint64(binary.LittleEndian.Uint16(fb[1:3]))
    96  	} else if fb[0] == byte(0xfe) {
    97  		_, err := io.ReadFull(reader, fb[1:5])
    98  		if err != nil {
    99  			return 0, err
   100  		}
   101  		res = uint64(binary.LittleEndian.Uint32(fb[1:5]))
   102  	} else if fb[0] == byte(0xff) {
   103  		_, err := io.ReadFull(reader, fb[1:9])
   104  		if err != nil {
   105  			return 0, err
   106  		}
   107  		res = uint64(binary.LittleEndian.Uint64(fb[1:9]))
   108  	} else {
   109  		res = uint64(fb[0])
   110  	}
   111  	if res > maxint {
   112  		return 0, ErrRange
   113  	}
   114  	return res, nil
   115  }
   116  
   117  func WriteVarBytes(writer io.Writer, value []byte) error {
   118  	err := WriteVarUint(writer, uint64(len(value)))
   119  	if err != nil {
   120  		return err
   121  	}
   122  	_, err = writer.Write(value)
   123  	return err
   124  }
   125  
   126  func WriteString(writer io.Writer, value string) error {
   127  	return WriteVarBytes(writer, []byte(value))
   128  }
   129  
   130  func ReadVarBytes(reader io.Reader) ([]byte, error) {
   131  	val, err := ReadVarUint(reader, 0)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	str, err := byteXReader(reader, val)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	return str, nil
   140  }
   141  
   142  func ReadString(reader io.Reader) (string, error) {
   143  	val, err := ReadVarBytes(reader)
   144  	if err != nil {
   145  		return "", err
   146  	}
   147  	return string(val), nil
   148  }
   149  
   150  func GetVarUintSize(value uint64) int {
   151  	if value < 0xfd {
   152  		return 1
   153  	} else if value <= 0xffff {
   154  		return 3
   155  	} else if value <= 0xFFFFFFFF {
   156  		return 5
   157  	} else {
   158  		return 9
   159  	}
   160  }
   161  
   162  func ReadBytes(reader io.Reader, length uint64) ([]byte, error) {
   163  	str, err := byteXReader(reader, length)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	return str, nil
   168  }
   169  
   170  func ReadUint8(reader io.Reader) (uint8, error) {
   171  	var p [1]byte
   172  	_, err := io.ReadFull(reader, p[:])
   173  	if err != nil {
   174  		return 0, ErrEof
   175  	}
   176  	return uint8(p[0]), nil
   177  }
   178  
   179  func ReadUint16(reader io.Reader) (uint16, error) {
   180  	var p [2]byte
   181  	_, err := io.ReadFull(reader, p[:])
   182  	if err != nil {
   183  		return 0, ErrEof
   184  	}
   185  	return binary.LittleEndian.Uint16(p[:]), nil
   186  }
   187  
   188  func ReadUint32(reader io.Reader) (uint32, error) {
   189  	var p [4]byte
   190  	_, err := io.ReadFull(reader, p[:])
   191  	if err != nil {
   192  		return 0, ErrEof
   193  	}
   194  	return binary.LittleEndian.Uint32(p[:]), nil
   195  }
   196  
   197  func ReadUint64(reader io.Reader) (uint64, error) {
   198  	var p [8]byte
   199  	_, err := io.ReadFull(reader, p[:])
   200  	if err != nil {
   201  		return 0, ErrEof
   202  	}
   203  	return binary.LittleEndian.Uint64(p[:]), nil
   204  }
   205  
   206  func WriteUint8(writer io.Writer, val uint8) error {
   207  	var p [1]byte
   208  	p[0] = byte(val)
   209  	_, err := writer.Write(p[:])
   210  	return err
   211  }
   212  
   213  func WriteUint16(writer io.Writer, val uint16) error {
   214  	var p [2]byte
   215  	binary.LittleEndian.PutUint16(p[:], val)
   216  	_, err := writer.Write(p[:])
   217  	return err
   218  }
   219  
   220  func WriteUint32(writer io.Writer, val uint32) error {
   221  	var p [4]byte
   222  	binary.LittleEndian.PutUint32(p[:], val)
   223  	_, err := writer.Write(p[:])
   224  	return err
   225  }
   226  
   227  func WriteUint64(writer io.Writer, val uint64) error {
   228  	var p [8]byte
   229  	binary.LittleEndian.PutUint64(p[:], val)
   230  	_, err := writer.Write(p[:])
   231  	return err
   232  }
   233  
   234  func ToArray(data SerializableData) []byte {
   235  	buf := new(bytes.Buffer)
   236  	data.Serialize(buf)
   237  	return buf.Bytes()
   238  }
   239  
   240  //**************************************************************************
   241  //**    internal func                                                    ***
   242  //**************************************************************************
   243  //** 2.byteXReader: read x byte and return []byte.
   244  //** 3.byteToUint8: change byte -> uint8 and return.
   245  //**************************************************************************
   246  
   247  func byteXReader(reader io.Reader, x uint64) ([]byte, error) {
   248  	if x == 0 {
   249  		return nil, nil
   250  	}
   251  	//fast path to avoid buffer reallocation
   252  	if x < 2*1024*1024 {
   253  		p := make([]byte, x)
   254  		_, err := io.ReadFull(reader, p)
   255  		if err != nil {
   256  			return nil, err
   257  		}
   258  		return p, nil
   259  	}
   260  
   261  	// normal path to avoid attack
   262  	limited := io.LimitReader(reader, int64(x))
   263  	buf := &bytes.Buffer{}
   264  	n, _ := buf.ReadFrom(limited)
   265  	if n == int64(x) {
   266  		return buf.Bytes(), nil
   267  	}
   268  	return nil, ErrEof
   269  }
   270  
   271  func WriteBool(writer io.Writer, val bool) error {
   272  	err := binary.Write(writer, binary.LittleEndian, val)
   273  	return err
   274  }
   275  
   276  func ReadBool(reader io.Reader) (bool, error) {
   277  	var x bool
   278  	err := binary.Read(reader, binary.LittleEndian, &x)
   279  	return x, err
   280  }
   281  
   282  func WriteByte(writer io.Writer, val byte) error {
   283  	_, err := writer.Write([]byte{val})
   284  	if err != nil {
   285  		return err
   286  	}
   287  	return nil
   288  }
   289  
   290  func ReadByte(reader io.Reader) (byte, error) {
   291  	b, err := byteXReader(reader, 1)
   292  	if err != nil {
   293  		return 0, err
   294  	}
   295  	return b[0], nil
   296  }