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 }