blob: 9a6b2f71206fcba898bab5e20f8916f04cdfd7f1 [file] [log] [blame]
Damien Neilba23aa52018-12-07 14:38:17 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style.
3// license that can be found in the LICENSE file.
4
5package proto
6
7import (
Damien Neil302cb322019-06-19 15:22:13 -07008 "google.golang.org/protobuf/internal/encoding/messageset"
Damien Neile89e6242019-05-13 23:55:40 -07009 "google.golang.org/protobuf/internal/encoding/wire"
10 "google.golang.org/protobuf/internal/errors"
Joe Tsai6e095992019-08-10 13:56:36 -070011 "google.golang.org/protobuf/internal/flags"
Damien Neile89e6242019-05-13 23:55:40 -070012 "google.golang.org/protobuf/internal/pragma"
13 "google.golang.org/protobuf/reflect/protoreflect"
14 "google.golang.org/protobuf/reflect/protoregistry"
15 "google.golang.org/protobuf/runtime/protoiface"
Damien Neilba23aa52018-12-07 14:38:17 -080016)
17
18// UnmarshalOptions configures the unmarshaler.
19//
20// Example usage:
21// err := UnmarshalOptions{DiscardUnknown: true}.Unmarshal(b, m)
22type UnmarshalOptions struct {
Joe Tsaif8b855d2019-07-12 13:37:59 -070023 pragma.NoUnkeyedLiterals
24
Joe Tsai705acad2019-09-14 18:22:59 -070025 // Merge merges the input into the destination message.
26 // The default behavior is to always reset the message before unmarshaling,
27 // unless Merge is specified.
28 Merge bool
29
Damien Neil96c229a2019-04-03 12:17:24 -070030 // AllowPartial accepts input for messages that will result in missing
31 // required fields. If AllowPartial is false (the default), Unmarshal will
32 // return an error if there are any missing required fields.
33 AllowPartial bool
34
Damien Neilba23aa52018-12-07 14:38:17 -080035 // If DiscardUnknown is set, unknown fields are ignored.
36 DiscardUnknown bool
37
Joe Tsaidb38ddd2019-05-07 15:14:40 -070038 // Resolver is used for looking up types when unmarshaling extension fields.
39 // If nil, this defaults to using protoregistry.GlobalTypes.
Joe Tsai1c283042019-05-14 14:28:19 -070040 Resolver interface {
Damien Neilf12fb452020-01-21 11:27:51 -080041 FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
42 FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error)
Joe Tsai1c283042019-05-14 14:28:19 -070043 }
Damien Neilba23aa52018-12-07 14:38:17 -080044}
45
Damien Neil0d3e8cc2019-04-01 13:31:55 -070046var _ = protoiface.UnmarshalOptions(UnmarshalOptions{})
47
Damien Neilba23aa52018-12-07 14:38:17 -080048// Unmarshal parses the wire-format message in b and places the result in m.
49func Unmarshal(b []byte, m Message) error {
Damien Neild30e5612020-01-22 10:28:16 -080050 _, err := UnmarshalOptions{}.unmarshal(b, m)
51 return err
Damien Neilba23aa52018-12-07 14:38:17 -080052}
53
54// Unmarshal parses the wire-format message in b and places the result in m.
55func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error {
Damien Neild30e5612020-01-22 10:28:16 -080056 _, err := o.unmarshal(b, m)
57 return err
58}
59
60// UnmarshalState parses a wire-format message and places the result in m.
61//
62// This method permits fine-grained control over the unmarshaler.
63// Most users should use Unmarshal instead.
64func (o UnmarshalOptions) UnmarshalState(m Message, in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
65 return o.unmarshal(in.Buf, m)
66}
67
68func (o UnmarshalOptions) unmarshal(b []byte, message Message) (out protoiface.UnmarshalOutput, err error) {
Joe Tsaidb38ddd2019-05-07 15:14:40 -070069 if o.Resolver == nil {
70 o.Resolver = protoregistry.GlobalTypes
71 }
Joe Tsai705acad2019-09-14 18:22:59 -070072 if !o.Merge {
Damien Neild30e5612020-01-22 10:28:16 -080073 Reset(message)
Joe Tsai705acad2019-09-14 18:22:59 -070074 }
Damien Neild30e5612020-01-22 10:28:16 -080075 allowPartial := o.AllowPartial
76 o.Merge = true
77 o.AllowPartial = true
78 m := message.ProtoReflect()
79 methods := protoMethods(m)
80 if methods != nil && methods.Unmarshal != nil &&
81 !(o.DiscardUnknown && methods.Flags&protoiface.SupportUnmarshalDiscardUnknown == 0) {
82 out, err = methods.Unmarshal(m, protoiface.UnmarshalInput{
83 Buf: b,
84 }, protoiface.UnmarshalOptions(o))
85 } else {
86 err = o.unmarshalMessageSlow(b, m)
87 }
Damien Neil8c86fc52019-06-19 09:28:29 -070088 if err != nil {
Damien Neild30e5612020-01-22 10:28:16 -080089 return out, err
Damien Neil0d3e8cc2019-04-01 13:31:55 -070090 }
Damien Neild30e5612020-01-22 10:28:16 -080091 if allowPartial {
92 return out, nil
Damien Neil4686e232019-04-05 13:31:40 -070093 }
Damien Neild30e5612020-01-22 10:28:16 -080094 return out, isInitialized(m)
Damien Neilba23aa52018-12-07 14:38:17 -080095}
96
Joe Tsai0f81b382019-07-10 23:14:31 -070097func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) error {
Damien Neild30e5612020-01-22 10:28:16 -080098 _, err := o.unmarshal(b, m.Interface())
99 return err
Damien Neil0d3e8cc2019-04-01 13:31:55 -0700100}
101
Joe Tsai0f81b382019-07-10 23:14:31 -0700102func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message) error {
Damien Neil302cb322019-06-19 15:22:13 -0700103 md := m.Descriptor()
104 if messageset.IsMessageSet(md) {
105 return unmarshalMessageSet(b, m, o)
106 }
107 fields := md.Fields()
Damien Neilba23aa52018-12-07 14:38:17 -0800108 for len(b) > 0 {
109 // Parse the tag (field number and wire type).
110 num, wtyp, tagLen := wire.ConsumeTag(b)
111 if tagLen < 0 {
112 return wire.ParseError(tagLen)
113 }
Damien Neilfe15dd42019-12-06 15:36:03 -0800114 if num > wire.MaxValidNumber {
115 return errors.New("invalid field number")
116 }
Damien Neilba23aa52018-12-07 14:38:17 -0800117
Joe Tsai6e095992019-08-10 13:56:36 -0700118 // Find the field descriptor for this field number.
Damien Neil302cb322019-06-19 15:22:13 -0700119 fd := fields.ByNumber(num)
120 if fd == nil && md.ExtensionRanges().Has(num) {
121 extType, err := o.Resolver.FindExtensionByNumber(md.FullName(), num)
Joe Tsai378c1322019-04-25 23:48:08 -0700122 if err != nil && err != protoregistry.NotFound {
123 return err
Joe Tsaidb38ddd2019-05-07 15:14:40 -0700124 }
Damien Neil92f76182019-08-02 16:58:08 -0700125 if extType != nil {
Damien Neil79bfdbe2019-08-28 11:08:22 -0700126 fd = extType.TypeDescriptor()
Damien Neil92f76182019-08-02 16:58:08 -0700127 }
Damien Neild068d302018-12-17 14:06:08 -0800128 }
Damien Neilba23aa52018-12-07 14:38:17 -0800129 var err error
Joe Tsai6e095992019-08-10 13:56:36 -0700130 if fd == nil {
131 err = errUnknown
132 } else if flags.ProtoLegacy {
133 if fd.IsWeak() && fd.Message().IsPlaceholder() {
134 err = errUnknown // weak referent is not linked in
135 }
136 }
137
138 // Parse the field value.
Damien Neilba23aa52018-12-07 14:38:17 -0800139 var valLen int
140 switch {
Joe Tsai6e095992019-08-10 13:56:36 -0700141 case err != nil:
Joe Tsai378c1322019-04-25 23:48:08 -0700142 case fd.IsList():
143 valLen, err = o.unmarshalList(b[tagLen:], wtyp, m.Mutable(fd).List(), fd)
144 case fd.IsMap():
145 valLen, err = o.unmarshalMap(b[tagLen:], wtyp, m.Mutable(fd).Map(), fd)
Joe Tsaiac31a352019-05-13 14:32:56 -0700146 default:
Joe Tsai378c1322019-04-25 23:48:08 -0700147 valLen, err = o.unmarshalSingular(b[tagLen:], wtyp, m, fd)
Damien Neilba23aa52018-12-07 14:38:17 -0800148 }
Joe Tsai6e095992019-08-10 13:56:36 -0700149 if err != nil {
150 if err != errUnknown {
151 return err
152 }
Damien Neilba23aa52018-12-07 14:38:17 -0800153 valLen = wire.ConsumeFieldValue(num, wtyp, b[tagLen:])
154 if valLen < 0 {
155 return wire.ParseError(valLen)
156 }
Damien Neila60e7092020-01-28 14:53:44 -0800157 if !o.DiscardUnknown {
158 m.SetUnknown(append(m.GetUnknown(), b[:tagLen+valLen]...))
159 }
Damien Neilba23aa52018-12-07 14:38:17 -0800160 }
161 b = b[tagLen+valLen:]
162 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700163 return nil
Damien Neilba23aa52018-12-07 14:38:17 -0800164}
165
Joe Tsai378c1322019-04-25 23:48:08 -0700166func (o UnmarshalOptions) unmarshalSingular(b []byte, wtyp wire.Type, m protoreflect.Message, fd protoreflect.FieldDescriptor) (n int, err error) {
Joe Tsai378c1322019-04-25 23:48:08 -0700167 v, n, err := o.unmarshalScalar(b, wtyp, fd)
Damien Neil8c86fc52019-06-19 09:28:29 -0700168 if err != nil {
Damien Neilba23aa52018-12-07 14:38:17 -0800169 return 0, err
170 }
Joe Tsai378c1322019-04-25 23:48:08 -0700171 switch fd.Kind() {
Damien Neilba23aa52018-12-07 14:38:17 -0800172 case protoreflect.GroupKind, protoreflect.MessageKind:
Joe Tsai6c286742019-07-11 23:15:05 -0700173 m2 := m.Mutable(fd).Message()
Damien Neil8c86fc52019-06-19 09:28:29 -0700174 if err := o.unmarshalMessage(v.Bytes(), m2); err != nil {
Damien Neilbc310b52019-04-11 11:46:55 -0700175 return n, err
176 }
Damien Neilba23aa52018-12-07 14:38:17 -0800177 default:
178 // Non-message scalars replace the previous value.
Joe Tsai378c1322019-04-25 23:48:08 -0700179 m.Set(fd, v)
Damien Neilba23aa52018-12-07 14:38:17 -0800180 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700181 return n, nil
Damien Neilba23aa52018-12-07 14:38:17 -0800182}
183
Joe Tsai378c1322019-04-25 23:48:08 -0700184func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp wire.Type, mapv protoreflect.Map, fd protoreflect.FieldDescriptor) (n int, err error) {
Damien Neilba23aa52018-12-07 14:38:17 -0800185 if wtyp != wire.BytesType {
186 return 0, errUnknown
187 }
188 b, n = wire.ConsumeBytes(b)
189 if n < 0 {
190 return 0, wire.ParseError(n)
191 }
192 var (
Joe Tsai378c1322019-04-25 23:48:08 -0700193 keyField = fd.MapKey()
194 valField = fd.MapValue()
Damien Neilba23aa52018-12-07 14:38:17 -0800195 key protoreflect.Value
196 val protoreflect.Value
197 haveKey bool
198 haveVal bool
199 )
200 switch valField.Kind() {
201 case protoreflect.GroupKind, protoreflect.MessageKind:
Damien Neild91c4222019-09-04 10:46:00 -0700202 val = mapv.NewValue()
Damien Neilba23aa52018-12-07 14:38:17 -0800203 }
204 // Map entries are represented as a two-element message with fields
205 // containing the key and value.
206 for len(b) > 0 {
207 num, wtyp, n := wire.ConsumeTag(b)
208 if n < 0 {
209 return 0, wire.ParseError(n)
210 }
Damien Neilf2427c02019-12-20 09:43:20 -0800211 if num > wire.MaxValidNumber {
212 return 0, errors.New("invalid field number")
213 }
Damien Neilba23aa52018-12-07 14:38:17 -0800214 b = b[n:]
215 err = errUnknown
216 switch num {
217 case 1:
Joe Tsai378c1322019-04-25 23:48:08 -0700218 key, n, err = o.unmarshalScalar(b, wtyp, keyField)
Damien Neil8c86fc52019-06-19 09:28:29 -0700219 if err != nil {
Damien Neilba23aa52018-12-07 14:38:17 -0800220 break
221 }
222 haveKey = true
223 case 2:
224 var v protoreflect.Value
Joe Tsai378c1322019-04-25 23:48:08 -0700225 v, n, err = o.unmarshalScalar(b, wtyp, valField)
Damien Neil8c86fc52019-06-19 09:28:29 -0700226 if err != nil {
Damien Neilba23aa52018-12-07 14:38:17 -0800227 break
228 }
229 switch valField.Kind() {
230 case protoreflect.GroupKind, protoreflect.MessageKind:
Damien Neil8c86fc52019-06-19 09:28:29 -0700231 if err := o.unmarshalMessage(v.Bytes(), val.Message()); err != nil {
Damien Neilba23aa52018-12-07 14:38:17 -0800232 return 0, err
233 }
234 default:
235 val = v
236 }
237 haveVal = true
238 }
239 if err == errUnknown {
240 n = wire.ConsumeFieldValue(num, wtyp, b)
241 if n < 0 {
242 return 0, wire.ParseError(n)
243 }
Damien Neilbc310b52019-04-11 11:46:55 -0700244 } else if err != nil {
Damien Neilba23aa52018-12-07 14:38:17 -0800245 return 0, err
246 }
247 b = b[n:]
248 }
249 // Every map entry should have entries for key and value, but this is not strictly required.
250 if !haveKey {
251 key = keyField.Default()
252 }
253 if !haveVal {
254 switch valField.Kind() {
255 case protoreflect.GroupKind, protoreflect.MessageKind:
Damien Neilba23aa52018-12-07 14:38:17 -0800256 default:
257 val = valField.Default()
258 }
259 }
260 mapv.Set(key.MapKey(), val)
Damien Neil8c86fc52019-06-19 09:28:29 -0700261 return n, nil
Damien Neilba23aa52018-12-07 14:38:17 -0800262}
263
264// errUnknown is used internally to indicate fields which should be added
265// to the unknown field set of a message. It is never returned from an exported
266// function.
Damien Neil96c229a2019-04-03 12:17:24 -0700267var errUnknown = errors.New("BUG: internal error (unknown)")