blob: 7c0da2384a7006d68ebd157c5caf399a7024788f [file] [log] [blame]
Herbie Ongc96a79d2019-03-08 10:49:17 -08001// Copyright 2019 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
Damien Neil5c5b5312019-05-14 12:44:37 -07005package protojson
Herbie Ongc96a79d2019-03-08 10:49:17 -08006
7import (
8 "encoding/base64"
9 "fmt"
10 "math"
11 "strconv"
12 "strings"
13
Damien Neile89e6242019-05-13 23:55:40 -070014 "google.golang.org/protobuf/internal/encoding/json"
Joe Tsai5ae10aa2019-07-11 18:23:08 -070015 "google.golang.org/protobuf/internal/encoding/messageset"
Damien Neile89e6242019-05-13 23:55:40 -070016 "google.golang.org/protobuf/internal/errors"
Joe Tsai5ae10aa2019-07-11 18:23:08 -070017 "google.golang.org/protobuf/internal/flags"
Damien Neile89e6242019-05-13 23:55:40 -070018 "google.golang.org/protobuf/internal/pragma"
19 "google.golang.org/protobuf/internal/set"
20 "google.golang.org/protobuf/proto"
21 pref "google.golang.org/protobuf/reflect/protoreflect"
22 "google.golang.org/protobuf/reflect/protoregistry"
Herbie Ongc96a79d2019-03-08 10:49:17 -080023)
24
25// Unmarshal reads the given []byte into the given proto.Message.
Joe Tsaicdb77732019-05-14 16:05:06 -070026func Unmarshal(b []byte, m proto.Message) error {
27 return UnmarshalOptions{}.Unmarshal(b, m)
Herbie Ongc96a79d2019-03-08 10:49:17 -080028}
29
30// UnmarshalOptions is a configurable JSON format parser.
Herbie Onge52379a2019-03-15 18:00:19 -070031type UnmarshalOptions struct {
32 pragma.NoUnkeyedLiterals
33
Herbie Ong4f0be712019-04-25 17:57:12 -070034 // If AllowPartial is set, input for messages that will result in missing
35 // required fields will not return an error.
Herbie Ong329be5b2019-03-27 14:47:59 -070036 AllowPartial bool
37
Herbie Ong4f0be712019-04-25 17:57:12 -070038 // If DiscardUnknown is set, unknown fields are ignored.
39 DiscardUnknown bool
40
Joe Tsai1c283042019-05-14 14:28:19 -070041 // Resolver is used for looking up types when unmarshaling
42 // google.protobuf.Any messages or extension fields.
43 // If nil, this defaults to using protoregistry.GlobalTypes.
44 Resolver interface {
45 protoregistry.MessageTypeResolver
46 protoregistry.ExtensionTypeResolver
47 }
Herbie Ong822de2d2019-03-27 13:16:23 -070048
49 decoder *json.Decoder
Herbie Onge52379a2019-03-15 18:00:19 -070050}
Herbie Ongc96a79d2019-03-08 10:49:17 -080051
52// Unmarshal reads the given []byte and populates the given proto.Message using
53// options in UnmarshalOptions object. It will clear the message first before
54// setting the fields. If it returns an error, the given message may be
55// partially set.
Joe Tsaicdb77732019-05-14 16:05:06 -070056func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -080057 // TODO: Determine if we would like to have an option for merging or only
Joe Tsai378c1322019-04-25 23:48:08 -070058 // have merging behavior. We should at least be consistent with textproto
Herbie Ongc96a79d2019-03-08 10:49:17 -080059 // marshaling.
Joe Tsai378c1322019-04-25 23:48:08 -070060 proto.Reset(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -080061
Herbie Ong822de2d2019-03-27 13:16:23 -070062 if o.Resolver == nil {
63 o.Resolver = protoregistry.GlobalTypes
Herbie Onge52379a2019-03-15 18:00:19 -070064 }
Herbie Ong822de2d2019-03-27 13:16:23 -070065 o.decoder = json.NewDecoder(b)
Herbie Onge52379a2019-03-15 18:00:19 -070066
Damien Neil8c86fc52019-06-19 09:28:29 -070067 if err := o.unmarshalMessage(m.ProtoReflect(), false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -080068 return err
69 }
70
71 // Check for EOF.
Herbie Ong822de2d2019-03-27 13:16:23 -070072 val, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -080073 if err != nil {
74 return err
75 }
76 if val.Type() != json.EOF {
77 return unexpectedJSONError{val}
78 }
Damien Neil4686e232019-04-05 13:31:40 -070079
Damien Neil8c86fc52019-06-19 09:28:29 -070080 if o.AllowPartial {
81 return nil
Damien Neil4686e232019-04-05 13:31:40 -070082 }
Damien Neil8c86fc52019-06-19 09:28:29 -070083 return proto.IsInitialized(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -080084}
85
Herbie Ongc96a79d2019-03-08 10:49:17 -080086// unexpectedJSONError is an error that contains the unexpected json.Value. This
Herbie Ong822de2d2019-03-27 13:16:23 -070087// is returned by methods to provide callers the read json.Value that it did not
88// expect.
Herbie Ongc96a79d2019-03-08 10:49:17 -080089// TODO: Consider moving this to internal/encoding/json for consistency with
90// errors that package returns.
91type unexpectedJSONError struct {
92 value json.Value
93}
94
95func (e unexpectedJSONError) Error() string {
96 return newError("unexpected value %s", e.value).Error()
97}
98
99// newError returns an error object. If one of the values passed in is of
100// json.Value type, it produces an error with position info.
101func newError(f string, x ...interface{}) error {
102 var hasValue bool
103 var line, column int
104 for i := 0; i < len(x); i++ {
105 if val, ok := x[i].(json.Value); ok {
106 line, column = val.Position()
107 hasValue = true
108 break
109 }
110 }
111 e := errors.New(f, x...)
112 if hasValue {
113 return errors.New("(line %d:%d): %v", line, column, e)
114 }
115 return e
116}
117
Herbie Ongc96a79d2019-03-08 10:49:17 -0800118// unmarshalMessage unmarshals a message into the given protoreflect.Message.
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700119func (o UnmarshalOptions) unmarshalMessage(m pref.Message, skipTypeURL bool) error {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700120 if isCustomType(m.Descriptor().FullName()) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700121 return o.unmarshalCustomType(m)
Herbie Onge63c4c42019-03-22 22:20:22 -0700122 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800123
Herbie Ong822de2d2019-03-27 13:16:23 -0700124 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700125 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800126 return err
127 }
128 if jval.Type() != json.StartObject {
129 return unexpectedJSONError{jval}
130 }
131
Damien Neil8c86fc52019-06-19 09:28:29 -0700132 if err := o.unmarshalFields(m, skipTypeURL); err != nil {
Herbie Onge63c4c42019-03-22 22:20:22 -0700133 return err
134 }
135
Damien Neil8c86fc52019-06-19 09:28:29 -0700136 return nil
Herbie Onge63c4c42019-03-22 22:20:22 -0700137}
138
139// unmarshalFields unmarshals the fields into the given protoreflect.Message.
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700140func (o UnmarshalOptions) unmarshalFields(m pref.Message, skipTypeURL bool) error {
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700141 messageDesc := m.Descriptor()
142 if !flags.Proto1Legacy && messageset.IsMessageSet(messageDesc) {
143 return errors.New("no support for proto1 MessageSets")
144 }
145
Herbie Onge63c4c42019-03-22 22:20:22 -0700146 var seenNums set.Ints
Herbie Ong8a1d4602019-04-02 20:19:36 -0700147 var seenOneofs set.Ints
Joe Tsai0fc49f82019-05-01 12:29:25 -0700148 fieldDescs := messageDesc.Fields()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800149 for {
150 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700151 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700152 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800153 return err
154 }
155 switch jval.Type() {
156 default:
157 return unexpectedJSONError{jval}
158 case json.EndObject:
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700159 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800160 case json.Name:
161 // Continue below.
162 }
163
164 name, err := jval.Name()
Damien Neil8c86fc52019-06-19 09:28:29 -0700165 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800166 return err
167 }
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700168 // Unmarshaling a non-custom embedded message in Any will contain the
169 // JSON field "@type" which should be skipped because it is not a field
170 // of the embedded message, but simply an artifact of the Any format.
171 if skipTypeURL && name == "@type" {
172 o.decoder.Read()
173 continue
174 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800175
Herbie Onge52379a2019-03-15 18:00:19 -0700176 // Get the FieldDescriptor.
177 var fd pref.FieldDescriptor
178 if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
179 // Only extension names are in [name] format.
Joe Tsai378c1322019-04-25 23:48:08 -0700180 extName := pref.FullName(name[1 : len(name)-1])
181 extType, err := o.findExtension(extName)
182 if err != nil && err != protoregistry.NotFound {
183 return errors.New("unable to resolve [%v]: %v", extName, err)
Herbie Onge52379a2019-03-15 18:00:19 -0700184 }
Joe Tsai378c1322019-04-25 23:48:08 -0700185 fd = extType
Herbie Onge52379a2019-03-15 18:00:19 -0700186 } else {
187 // The name can either be the JSON name or the proto field name.
188 fd = fieldDescs.ByJSONName(name)
189 if fd == nil {
190 fd = fieldDescs.ByName(pref.Name(name))
191 }
Joe Tsaid47ea192019-07-09 22:38:15 -0700192 if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
193 fd = nil // reset since the weak reference is not linked in
194 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800195 }
196
197 if fd == nil {
198 // Field is unknown.
Herbie Ong4f0be712019-04-25 17:57:12 -0700199 if o.DiscardUnknown {
Damien Neil8c86fc52019-06-19 09:28:29 -0700200 if err := skipJSONValue(o.decoder); err != nil {
Herbie Ong4f0be712019-04-25 17:57:12 -0700201 return err
202 }
203 continue
204 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700205 return newError("%v contains unknown field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800206 }
207
208 // Do not allow duplicate fields.
209 num := uint64(fd.Number())
210 if seenNums.Has(num) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700211 return newError("%v contains repeated field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800212 }
213 seenNums.Set(num)
214
Herbie Onge63c4c42019-03-22 22:20:22 -0700215 // No need to set values for JSON null unless the field type is
Herbie Ong300b9fe2019-03-29 15:42:20 -0700216 // google.protobuf.Value or google.protobuf.NullValue.
217 if o.decoder.Peek() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700218 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800219 continue
220 }
221
Joe Tsaiac31a352019-05-13 14:32:56 -0700222 switch {
223 case fd.IsList():
Joe Tsai378c1322019-04-25 23:48:08 -0700224 list := m.Mutable(fd).List()
Damien Neil8c86fc52019-06-19 09:28:29 -0700225 if err := o.unmarshalList(list, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800226 return errors.New("%v|%q: %v", fd.FullName(), name, err)
227 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700228 case fd.IsMap():
Joe Tsai378c1322019-04-25 23:48:08 -0700229 mmap := m.Mutable(fd).Map()
Damien Neil8c86fc52019-06-19 09:28:29 -0700230 if err := o.unmarshalMap(mmap, fd); err != nil {
Joe Tsaiac31a352019-05-13 14:32:56 -0700231 return errors.New("%v|%q: %v", fd.FullName(), name, err)
232 }
233 default:
Herbie Ong8a1d4602019-04-02 20:19:36 -0700234 // If field is a oneof, check if it has already been set.
Joe Tsaiac31a352019-05-13 14:32:56 -0700235 if od := fd.ContainingOneof(); od != nil {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700236 idx := uint64(od.Index())
237 if seenOneofs.Has(idx) {
238 return errors.New("%v: oneof is already set", od.FullName())
239 }
240 seenOneofs.Set(idx)
241 }
242
Herbie Ongc96a79d2019-03-08 10:49:17 -0800243 // Required or optional fields.
Damien Neil8c86fc52019-06-19 09:28:29 -0700244 if err := o.unmarshalSingular(m, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800245 return errors.New("%v|%q: %v", fd.FullName(), name, err)
246 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800247 }
248 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800249}
250
Herbie Onge52379a2019-03-15 18:00:19 -0700251// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700252func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
253 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700254 if err == nil {
255 return xt, nil
256 }
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700257 return messageset.FindMessageSetExtension(o.Resolver, xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700258}
259
Herbie Ong300b9fe2019-03-29 15:42:20 -0700260func isKnownValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700261 md := fd.Message()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700262 return md != nil && md.FullName() == "google.protobuf.Value"
263}
264
265func isNullValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700266 ed := fd.Enum()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700267 return ed != nil && ed.FullName() == "google.protobuf.NullValue"
268}
269
Herbie Ongc96a79d2019-03-08 10:49:17 -0800270// unmarshalSingular unmarshals to the non-repeated field specified by the given
271// FieldDescriptor.
Joe Tsai378c1322019-04-25 23:48:08 -0700272func (o UnmarshalOptions) unmarshalSingular(m pref.Message, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800273 var val pref.Value
274 var err error
Herbie Ongc96a79d2019-03-08 10:49:17 -0800275 switch fd.Kind() {
276 case pref.MessageKind, pref.GroupKind:
Joe Tsai378c1322019-04-25 23:48:08 -0700277 m2 := m.NewMessage(fd)
278 err = o.unmarshalMessage(m2, false)
279 val = pref.ValueOf(m2)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800280 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700281 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800282 }
283
Damien Neil8c86fc52019-06-19 09:28:29 -0700284 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800285 return err
286 }
Joe Tsai378c1322019-04-25 23:48:08 -0700287 m.Set(fd, val)
Damien Neil8c86fc52019-06-19 09:28:29 -0700288 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800289}
290
291// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
292// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700293func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800294 const b32 int = 32
295 const b64 int = 64
296
Herbie Ong822de2d2019-03-27 13:16:23 -0700297 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700298 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800299 return pref.Value{}, err
300 }
301
302 kind := fd.Kind()
303 switch kind {
304 case pref.BoolKind:
305 return unmarshalBool(jval)
306
307 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
308 return unmarshalInt(jval, b32)
309
310 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
311 return unmarshalInt(jval, b64)
312
313 case pref.Uint32Kind, pref.Fixed32Kind:
314 return unmarshalUint(jval, b32)
315
316 case pref.Uint64Kind, pref.Fixed64Kind:
317 return unmarshalUint(jval, b64)
318
319 case pref.FloatKind:
320 return unmarshalFloat(jval, b32)
321
322 case pref.DoubleKind:
323 return unmarshalFloat(jval, b64)
324
325 case pref.StringKind:
326 pval, err := unmarshalString(jval)
Damien Neil8c86fc52019-06-19 09:28:29 -0700327 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800328 return pval, err
329 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700330 return pval, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800331
332 case pref.BytesKind:
333 return unmarshalBytes(jval)
334
335 case pref.EnumKind:
336 return unmarshalEnum(jval, fd)
337 }
338
339 panic(fmt.Sprintf("invalid scalar kind %v", kind))
340}
341
342func unmarshalBool(jval json.Value) (pref.Value, error) {
343 if jval.Type() != json.Bool {
344 return pref.Value{}, unexpectedJSONError{jval}
345 }
346 b, err := jval.Bool()
347 return pref.ValueOf(b), err
348}
349
350func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
351 switch jval.Type() {
352 case json.Number:
353 return getInt(jval, bitSize)
354
355 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700356 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700357 s := strings.TrimSpace(jval.String())
358 if len(s) != len(jval.String()) {
359 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
360 }
361 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800362 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700363 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800364 return pref.Value{}, err
365 }
366 return getInt(jval, bitSize)
367 }
368 return pref.Value{}, unexpectedJSONError{jval}
369}
370
371func getInt(jval json.Value, bitSize int) (pref.Value, error) {
372 n, err := jval.Int(bitSize)
373 if err != nil {
374 return pref.Value{}, err
375 }
376 if bitSize == 32 {
377 return pref.ValueOf(int32(n)), nil
378 }
379 return pref.ValueOf(n), nil
380}
381
382func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
383 switch jval.Type() {
384 case json.Number:
385 return getUint(jval, bitSize)
386
387 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700388 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700389 s := strings.TrimSpace(jval.String())
390 if len(s) != len(jval.String()) {
391 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
392 }
393 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800394 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700395 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800396 return pref.Value{}, err
397 }
398 return getUint(jval, bitSize)
399 }
400 return pref.Value{}, unexpectedJSONError{jval}
401}
402
403func getUint(jval json.Value, bitSize int) (pref.Value, error) {
404 n, err := jval.Uint(bitSize)
405 if err != nil {
406 return pref.Value{}, err
407 }
408 if bitSize == 32 {
409 return pref.ValueOf(uint32(n)), nil
410 }
411 return pref.ValueOf(n), nil
412}
413
414func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
415 switch jval.Type() {
416 case json.Number:
417 return getFloat(jval, bitSize)
418
419 case json.String:
420 s := jval.String()
421 switch s {
422 case "NaN":
423 if bitSize == 32 {
424 return pref.ValueOf(float32(math.NaN())), nil
425 }
426 return pref.ValueOf(math.NaN()), nil
427 case "Infinity":
428 if bitSize == 32 {
429 return pref.ValueOf(float32(math.Inf(+1))), nil
430 }
431 return pref.ValueOf(math.Inf(+1)), nil
432 case "-Infinity":
433 if bitSize == 32 {
434 return pref.ValueOf(float32(math.Inf(-1))), nil
435 }
436 return pref.ValueOf(math.Inf(-1)), nil
437 }
Herbie Onge52379a2019-03-15 18:00:19 -0700438 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700439 if len(s) != len(strings.TrimSpace(s)) {
440 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
441 }
Herbie Onge52379a2019-03-15 18:00:19 -0700442 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800443 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700444 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800445 return pref.Value{}, err
446 }
447 return getFloat(jval, bitSize)
448 }
449 return pref.Value{}, unexpectedJSONError{jval}
450}
451
452func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
453 n, err := jval.Float(bitSize)
454 if err != nil {
455 return pref.Value{}, err
456 }
457 if bitSize == 32 {
458 return pref.ValueOf(float32(n)), nil
459 }
460 return pref.ValueOf(n), nil
461}
462
463func unmarshalString(jval json.Value) (pref.Value, error) {
464 if jval.Type() != json.String {
465 return pref.Value{}, unexpectedJSONError{jval}
466 }
467 return pref.ValueOf(jval.String()), nil
468}
469
470func unmarshalBytes(jval json.Value) (pref.Value, error) {
471 if jval.Type() != json.String {
472 return pref.Value{}, unexpectedJSONError{jval}
473 }
474
475 s := jval.String()
476 enc := base64.StdEncoding
477 if strings.ContainsAny(s, "-_") {
478 enc = base64.URLEncoding
479 }
480 if len(s)%4 != 0 {
481 enc = enc.WithPadding(base64.NoPadding)
482 }
483 b, err := enc.DecodeString(s)
484 if err != nil {
485 return pref.Value{}, err
486 }
487 return pref.ValueOf(b), nil
488}
489
490func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
491 switch jval.Type() {
492 case json.String:
493 // Lookup EnumNumber based on name.
494 s := jval.String()
Joe Tsaid24bc722019-04-15 23:39:09 -0700495 if enumVal := fd.Enum().Values().ByName(pref.Name(s)); enumVal != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800496 return pref.ValueOf(enumVal.Number()), nil
497 }
498 return pref.Value{}, newError("invalid enum value %q", jval)
499
500 case json.Number:
501 n, err := jval.Int(32)
502 if err != nil {
503 return pref.Value{}, err
504 }
505 return pref.ValueOf(pref.EnumNumber(n)), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700506
507 case json.Null:
508 // This is only valid for google.protobuf.NullValue.
509 if isNullValue(fd) {
510 return pref.ValueOf(pref.EnumNumber(0)), nil
511 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800512 }
513
514 return pref.Value{}, unexpectedJSONError{jval}
515}
516
Herbie Ong822de2d2019-03-27 13:16:23 -0700517func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700518 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700519 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800520 return err
521 }
522 if jval.Type() != json.StartArray {
523 return unexpectedJSONError{jval}
524 }
525
526 switch fd.Kind() {
527 case pref.MessageKind, pref.GroupKind:
528 for {
529 m := list.NewMessage()
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700530 err := o.unmarshalMessage(m, false)
Damien Neil8c86fc52019-06-19 09:28:29 -0700531 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800532 if e, ok := err.(unexpectedJSONError); ok {
533 if e.value.Type() == json.EndArray {
534 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700535 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800536 }
537 }
538 return err
539 }
540 list.Append(pref.ValueOf(m))
541 }
542 default:
543 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700544 val, err := o.unmarshalScalar(fd)
Damien Neil8c86fc52019-06-19 09:28:29 -0700545 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800546 if e, ok := err.(unexpectedJSONError); ok {
547 if e.value.Type() == json.EndArray {
548 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700549 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800550 }
551 }
552 return err
553 }
554 list.Append(val)
555 }
556 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700557 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800558}
559
Herbie Ong822de2d2019-03-27 13:16:23 -0700560func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700561 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700562 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800563 return err
564 }
565 if jval.Type() != json.StartObject {
566 return unexpectedJSONError{jval}
567 }
568
Herbie Ongc96a79d2019-03-08 10:49:17 -0800569 // Determine ahead whether map entry is a scalar type or a message type in
570 // order to call the appropriate unmarshalMapValue func inside the for loop
571 // below.
Joe Tsaiac31a352019-05-13 14:32:56 -0700572 var unmarshalMapValue func() (pref.Value, error)
573 switch fd.MapValue().Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800574 case pref.MessageKind, pref.GroupKind:
575 unmarshalMapValue = func() (pref.Value, error) {
576 m := mmap.NewMessage()
Damien Neil8c86fc52019-06-19 09:28:29 -0700577 if err := o.unmarshalMessage(m, false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800578 return pref.Value{}, err
579 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700580 return pref.ValueOf(m), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800581 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700582 default:
583 unmarshalMapValue = func() (pref.Value, error) {
584 return o.unmarshalScalar(fd.MapValue())
585 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800586 }
587
588Loop:
589 for {
590 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700591 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700592 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800593 return err
594 }
595 switch jval.Type() {
596 default:
597 return unexpectedJSONError{jval}
598 case json.EndObject:
599 break Loop
600 case json.Name:
601 // Continue.
602 }
603
604 name, err := jval.Name()
Damien Neil8c86fc52019-06-19 09:28:29 -0700605 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800606 return err
607 }
608
609 // Unmarshal field name.
Joe Tsaiac31a352019-05-13 14:32:56 -0700610 pkey, err := unmarshalMapKey(name, fd.MapKey())
Damien Neil8c86fc52019-06-19 09:28:29 -0700611 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800612 return err
613 }
614
615 // Check for duplicate field name.
616 if mmap.Has(pkey) {
617 return newError("duplicate map key %q", jval)
618 }
619
620 // Read and unmarshal field value.
621 pval, err := unmarshalMapValue()
Damien Neil8c86fc52019-06-19 09:28:29 -0700622 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800623 return err
624 }
625
626 mmap.Set(pkey, pval)
627 }
628
Damien Neil8c86fc52019-06-19 09:28:29 -0700629 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800630}
631
632// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
633// integral or string type.
634func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
635 const b32 = 32
636 const b64 = 64
637 const base10 = 10
638
639 kind := fd.Kind()
640 switch kind {
641 case pref.StringKind:
642 return pref.ValueOf(name).MapKey(), nil
643
644 case pref.BoolKind:
645 switch name {
646 case "true":
647 return pref.ValueOf(true).MapKey(), nil
648 case "false":
649 return pref.ValueOf(false).MapKey(), nil
650 }
651 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
652
653 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
654 n, err := strconv.ParseInt(name, base10, b32)
655 if err != nil {
656 return pref.MapKey{}, err
657 }
658 return pref.ValueOf(int32(n)).MapKey(), nil
659
660 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
661 n, err := strconv.ParseInt(name, base10, b64)
662 if err != nil {
663 return pref.MapKey{}, err
664 }
665 return pref.ValueOf(int64(n)).MapKey(), nil
666
667 case pref.Uint32Kind, pref.Fixed32Kind:
668 n, err := strconv.ParseUint(name, base10, b32)
669 if err != nil {
670 return pref.MapKey{}, err
671 }
672 return pref.ValueOf(uint32(n)).MapKey(), nil
673
674 case pref.Uint64Kind, pref.Fixed64Kind:
675 n, err := strconv.ParseUint(name, base10, b64)
676 if err != nil {
677 return pref.MapKey{}, err
678 }
679 return pref.ValueOf(uint64(n)).MapKey(), nil
680 }
681
682 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
683}