github.com/MagHErmit/tendermint@v0.282.1/libs/protoio/writer.go (about) 1 // Protocol Buffers for Go with Gadgets 2 // 3 // Copyright (c) 2013, The GoGo Authors. All rights reserved. 4 // http://github.com/gogo/protobuf 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 // 29 // Modified from original GoGo Protobuf to return number of bytes written. 30 31 package protoio 32 33 import ( 34 "bytes" 35 "encoding/binary" 36 "io" 37 38 "github.com/gogo/protobuf/proto" 39 ) 40 41 // NewDelimitedWriter writes a varint-delimited Protobuf message to a writer. It is 42 // equivalent to the gogoproto NewDelimitedWriter, except WriteMsg() also returns the 43 // number of bytes written, which is necessary in the p2p package. 44 func NewDelimitedWriter(w io.Writer) WriteCloser { 45 return &varintWriter{w, make([]byte, binary.MaxVarintLen64), nil} 46 } 47 48 type varintWriter struct { 49 w io.Writer 50 lenBuf []byte 51 buffer []byte 52 } 53 54 func (w *varintWriter) WriteMsg(msg proto.Message) (int, error) { 55 if m, ok := msg.(marshaler); ok { 56 n, ok := getSize(m) 57 if ok { 58 if n+binary.MaxVarintLen64 >= len(w.buffer) { 59 w.buffer = make([]byte, n+binary.MaxVarintLen64) 60 } 61 lenOff := binary.PutUvarint(w.buffer, uint64(n)) 62 _, err := m.MarshalTo(w.buffer[lenOff:]) 63 if err != nil { 64 return 0, err 65 } 66 _, err = w.w.Write(w.buffer[:lenOff+n]) 67 return lenOff + n, err 68 } 69 } 70 71 // fallback 72 data, err := proto.Marshal(msg) 73 if err != nil { 74 return 0, err 75 } 76 length := uint64(len(data)) 77 n := binary.PutUvarint(w.lenBuf, length) 78 _, err = w.w.Write(w.lenBuf[:n]) 79 if err != nil { 80 return 0, err 81 } 82 _, err = w.w.Write(data) 83 return len(data) + n, err 84 } 85 86 func (w *varintWriter) Close() error { 87 if closer, ok := w.w.(io.Closer); ok { 88 return closer.Close() 89 } 90 return nil 91 } 92 93 func MarshalDelimited(msg proto.Message) ([]byte, error) { 94 var buf bytes.Buffer 95 _, err := NewDelimitedWriter(&buf).WriteMsg(msg) 96 if err != nil { 97 return nil, err 98 } 99 return buf.Bytes(), nil 100 }