github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/encoding/prefix.go (about)

     1  package encoding
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  )
     7  
     8  // ReadPrefix reads an 8-byte length prefixes, followed by the number of bytes
     9  // specified in the prefix. The operation is aborted if the prefix exceeds a
    10  // specified maximum length.
    11  func ReadPrefix(r io.Reader, maxLen uint64) ([]byte, error) {
    12  	prefix := make([]byte, 8)
    13  	if _, err := io.ReadFull(r, prefix); err != nil {
    14  		return nil, err
    15  	}
    16  	dataLen := DecUint64(prefix)
    17  	if dataLen > maxLen {
    18  		return nil, fmt.Errorf("length %d exceeds maxLen of %d", dataLen, maxLen)
    19  	}
    20  	// read dataLen bytes
    21  	data := make([]byte, dataLen)
    22  	_, err := io.ReadFull(r, data)
    23  	return data, err
    24  }
    25  
    26  // ReadObject reads and decodes a length-prefixed and marshalled object.
    27  func ReadObject(r io.Reader, obj interface{}, maxLen uint64) error {
    28  	data, err := ReadPrefix(r, maxLen)
    29  	if err != nil {
    30  		return err
    31  	}
    32  	return Unmarshal(data, obj)
    33  }
    34  
    35  // WritePrefix writes a length-prefixed byte slice to w.
    36  func WritePrefix(w io.Writer, data []byte) error {
    37  	n, err := w.Write(EncUint64(uint64(len(data))))
    38  	if err != nil {
    39  		return err
    40  	} else if n != 8 {
    41  		return io.ErrShortWrite
    42  	}
    43  	n, err = w.Write(data)
    44  	if err == nil && n != len(data) {
    45  		err = io.ErrShortWrite
    46  	}
    47  	return err
    48  }
    49  
    50  // WriteObject writes a length-prefixed object to w.
    51  func WriteObject(w io.Writer, v interface{}) error {
    52  	return WritePrefix(w, Marshal(v))
    53  }