github.com/jhump/protoreflect@v1.16.0/dynamic/binary.go (about)

     1  package dynamic
     2  
     3  // Binary serialization and de-serialization for dynamic messages
     4  
     5  import (
     6  	"fmt"
     7  	"io"
     8  
     9  	"github.com/golang/protobuf/proto"
    10  
    11  	"github.com/jhump/protoreflect/codec"
    12  )
    13  
    14  // defaultDeterminism, if true, will mean that calls to Marshal will produce
    15  // deterministic output. This is used to make the output of proto.Marshal(...)
    16  // deterministic (since there is no way to have that convey determinism intent).
    17  // **This is only used from tests.**
    18  var defaultDeterminism = false
    19  
    20  // Marshal serializes this message to bytes, returning an error if the operation
    21  // fails. The resulting bytes are in the standard protocol buffer binary format.
    22  func (m *Message) Marshal() ([]byte, error) {
    23  	var b codec.Buffer
    24  	b.SetDeterministic(defaultDeterminism)
    25  	if err := m.marshal(&b); err != nil {
    26  		return nil, err
    27  	}
    28  	return b.Bytes(), nil
    29  }
    30  
    31  // MarshalAppend behaves exactly the same as Marshal, except instead of allocating a
    32  // new byte slice to marshal into, it uses the provided byte slice. The backing array
    33  // for the returned byte slice *may* be the same as the one that was passed in, but
    34  // it's not guaranteed as a new backing array will automatically be allocated if
    35  // more bytes need to be written than the provided buffer has capacity for.
    36  func (m *Message) MarshalAppend(b []byte) ([]byte, error) {
    37  	codedBuf := codec.NewBuffer(b)
    38  	codedBuf.SetDeterministic(defaultDeterminism)
    39  	if err := m.marshal(codedBuf); err != nil {
    40  		return nil, err
    41  	}
    42  	return codedBuf.Bytes(), nil
    43  }
    44  
    45  // MarshalDeterministic serializes this message to bytes in a deterministic way,
    46  // returning an error if the operation fails. This differs from Marshal in that
    47  // map keys will be sorted before serializing to bytes. The protobuf spec does
    48  // not define ordering for map entries, so Marshal will use standard Go map
    49  // iteration order (which will be random). But for cases where determinism is
    50  // more important than performance, use this method instead.
    51  func (m *Message) MarshalDeterministic() ([]byte, error) {
    52  	var b codec.Buffer
    53  	b.SetDeterministic(true)
    54  	if err := m.marshal(&b); err != nil {
    55  		return nil, err
    56  	}
    57  	return b.Bytes(), nil
    58  }
    59  
    60  // MarshalAppendDeterministic behaves exactly the same as MarshalDeterministic,
    61  // except instead of allocating a new byte slice to marshal into, it uses the
    62  // provided byte slice. The backing array for the returned byte slice *may* be
    63  // the same as the one that was passed in, but it's not guaranteed as a new
    64  // backing array will automatically be allocated if more bytes need to be written
    65  // than the provided buffer has capacity for.
    66  func (m *Message) MarshalAppendDeterministic(b []byte) ([]byte, error) {
    67  	codedBuf := codec.NewBuffer(b)
    68  	codedBuf.SetDeterministic(true)
    69  	if err := m.marshal(codedBuf); err != nil {
    70  		return nil, err
    71  	}
    72  	return codedBuf.Bytes(), nil
    73  }
    74  
    75  func (m *Message) marshal(b *codec.Buffer) error {
    76  	if m.GetMessageDescriptor().GetMessageOptions().GetMessageSetWireFormat() {
    77  		return fmt.Errorf("%s is a message set; marshaling message sets is not implemented", m.GetMessageDescriptor().GetFullyQualifiedName())
    78  	}
    79  	if err := m.marshalKnownFields(b); err != nil {
    80  		return err
    81  	}
    82  	return m.marshalUnknownFields(b)
    83  }
    84  
    85  func (m *Message) marshalKnownFields(b *codec.Buffer) error {
    86  	for _, tag := range m.knownFieldTags() {
    87  		itag := int32(tag)
    88  		val := m.values[itag]
    89  		fd := m.FindFieldDescriptor(itag)
    90  		if fd == nil {
    91  			panic(fmt.Sprintf("Couldn't find field for tag %d", itag))
    92  		}
    93  		if err := b.EncodeFieldValue(fd, val); err != nil {
    94  			return err
    95  		}
    96  	}
    97  	return nil
    98  }
    99  
   100  func (m *Message) marshalUnknownFields(b *codec.Buffer) error {
   101  	for _, tag := range m.unknownFieldTags() {
   102  		itag := int32(tag)
   103  		sl := m.unknownFields[itag]
   104  		for _, u := range sl {
   105  			if err := b.EncodeTagAndWireType(itag, u.Encoding); err != nil {
   106  				return err
   107  			}
   108  			switch u.Encoding {
   109  			case proto.WireBytes:
   110  				if err := b.EncodeRawBytes(u.Contents); err != nil {
   111  					return err
   112  				}
   113  			case proto.WireStartGroup:
   114  				_, _ = b.Write(u.Contents)
   115  				if err := b.EncodeTagAndWireType(itag, proto.WireEndGroup); err != nil {
   116  					return err
   117  				}
   118  			case proto.WireFixed32:
   119  				if err := b.EncodeFixed32(u.Value); err != nil {
   120  					return err
   121  				}
   122  			case proto.WireFixed64:
   123  				if err := b.EncodeFixed64(u.Value); err != nil {
   124  					return err
   125  				}
   126  			case proto.WireVarint:
   127  				if err := b.EncodeVarint(u.Value); err != nil {
   128  					return err
   129  				}
   130  			default:
   131  				return codec.ErrBadWireType
   132  			}
   133  		}
   134  	}
   135  	return nil
   136  }
   137  
   138  // Unmarshal de-serializes the message that is present in the given bytes into
   139  // this message. It first resets the current message. It returns an error if the
   140  // given bytes do not contain a valid encoding of this message type.
   141  func (m *Message) Unmarshal(b []byte) error {
   142  	m.Reset()
   143  	if err := m.UnmarshalMerge(b); err != nil {
   144  		return err
   145  	}
   146  	return m.Validate()
   147  }
   148  
   149  // UnmarshalMerge de-serializes the message that is present in the given bytes
   150  // into this message. Unlike Unmarshal, it does not first reset the message,
   151  // instead merging the data in the given bytes into the existing data in this
   152  // message.
   153  func (m *Message) UnmarshalMerge(b []byte) error {
   154  	return m.unmarshal(codec.NewBuffer(b), false)
   155  }
   156  
   157  func (m *Message) unmarshal(buf *codec.Buffer, isGroup bool) error {
   158  	if m.GetMessageDescriptor().GetMessageOptions().GetMessageSetWireFormat() {
   159  		return fmt.Errorf("%s is a message set; unmarshaling message sets is not implemented", m.GetMessageDescriptor().GetFullyQualifiedName())
   160  	}
   161  	for !buf.EOF() {
   162  		fd, val, err := buf.DecodeFieldValue(m.FindFieldDescriptor, m.mf)
   163  		if err != nil {
   164  			if err == codec.ErrWireTypeEndGroup {
   165  				if isGroup {
   166  					// finished parsing group
   167  					return nil
   168  				}
   169  				return codec.ErrBadWireType
   170  			}
   171  			return err
   172  		}
   173  
   174  		if fd == nil {
   175  			if m.unknownFields == nil {
   176  				m.unknownFields = map[int32][]UnknownField{}
   177  			}
   178  			uv := val.(codec.UnknownField)
   179  			u := UnknownField{
   180  				Encoding: uv.Encoding,
   181  				Value:    uv.Value,
   182  				Contents: uv.Contents,
   183  			}
   184  			m.unknownFields[uv.Tag] = append(m.unknownFields[uv.Tag], u)
   185  		} else if err := mergeField(m, fd, val); err != nil {
   186  			return err
   187  		}
   188  	}
   189  	if isGroup {
   190  		return io.ErrUnexpectedEOF
   191  	}
   192  	return nil
   193  }