Index: proto/decode.go |
=================================================================== |
--- a/proto/decode.go |
+++ b/proto/decode.go |
@@ -699,3 +699,34 @@ |
return err |
} |
+ |
+// ReadDelimited decodes a message from the provided length-delimited stream, |
+// where the length is encoded as 64-bit varint prefix to the message body. |
+// It returns the total number of bytes read and any applicable error. |
+func ReadDelimited(r io.Reader, m Message) (n int, err error) { |
+ buffer := make([]byte, maxVarintBytes) |
+ |
+ headerLength, err := r.Read(buffer) |
+ if err != nil { |
+ return headerLength, err |
+ } |
+ if headerLength == 0 || int(buffer[0]) == -1 { |
+ return headerLength, io.EOF |
+ } |
+ |
+ messageLength, syncLength := DecodeVarint(buffer) |
+ buffer = buffer[syncLength:] |
+ |
+ remainder := make([]byte, int(messageLength)-len(buffer)) |
+ remainderLength, err := r.Read(remainder) |
+ if err != nil { |
+ return headerLength + remainderLength, err |
+ } |
+ if len(buffer)+len(remainder) != int(messageLength) { |
+ return headerLength + remainderLength, fmt.Errorf("truncated message") |
+ } |
+ |
+ buffer = append(buffer, remainder...) |
+ |
+ return headerLength + remainderLength, Unmarshal(buffer, m) |
+} |