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 }