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  }