github.com/cockroachdb/cockroachdb-parser@v0.23.3-0.20240213214944-911057d40c9a/pkg/util/protoutil/marshal.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package protoutil 12 13 import ( 14 "fmt" 15 16 "github.com/cockroachdb/cockroachdb-parser/pkg/util/buildutil" 17 "github.com/gogo/protobuf/proto" 18 ) 19 20 // Message extends the proto.Message interface with the MarshalTo and Size 21 // methods we tell gogoproto to generate for us. 22 type Message interface { 23 proto.Message 24 MarshalTo(data []byte) (int, error) 25 MarshalToSizedBuffer(data []byte) (int, error) 26 Unmarshal(data []byte) error 27 Size() int 28 } 29 30 // Marshal encodes pb into the wire format and returns the resulting byte slice. 31 func Marshal(pb Message) ([]byte, error) { 32 dest := make([]byte, pb.Size()) 33 if _, err := MarshalToSizedBuffer(pb, dest); err != nil { 34 return nil, err 35 } 36 return dest, nil 37 } 38 39 // MarshalTo encodes pb into the wire format and writes the result into the 40 // provided byte slice, returning the number of bytes written. 41 // 42 // dest is required to have a capacity of at least pb.Size() bytes. 43 func MarshalTo(pb Message, dest []byte) (int, error) { 44 if buildutil.CrdbTestBuild { 45 if pb.Size() > cap(dest) { 46 panic(fmt.Sprintf("MarshalTo called for %T with slice with insufficient "+ 47 "capacity: pb.Size()=%d, cap(dest)=%d", pb, pb.Size(), cap(dest))) 48 } 49 } 50 return pb.MarshalTo(dest) 51 } 52 53 // MarshalToSizedBuffer encodes pb into the wire format and writes the result 54 // into the provided byte slice, returning the number of bytes written. 55 // 56 // dest is required to have a length of exactly pb.Size() bytes. 57 func MarshalToSizedBuffer(pb Message, dest []byte) (int, error) { 58 if buildutil.CrdbTestBuild { 59 if pb.Size() != len(dest) { 60 panic(fmt.Sprintf("MarshalToSizedBuffer called for %T with slice with "+ 61 "incorrect length: pb.Size()=%d, len(dest)=%d", pb, pb.Size(), len(dest))) 62 } 63 } 64 return pb.MarshalToSizedBuffer(dest) 65 } 66 67 // Unmarshal parses the protocol buffer representation in buf and places the 68 // decoded result in pb. If the struct underlying pb does not match the data in 69 // buf, the results can be unpredictable. 70 // 71 // Unmarshal resets pb before starting to unmarshal, so any existing data in pb 72 // is always removed. 73 func Unmarshal(data []byte, pb Message) error { 74 pb.Reset() 75 return pb.Unmarshal(data) 76 }