blob: 5e32d8b484fa6a4c8963984cbb5df4b2d70c64c4 [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()
Joe Tsai1799d112019-08-08 13:31:59 -0700142 if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) {
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700143 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 }
Damien Neil92f76182019-08-02 16:58:08 -0700185 if extType != nil {
186 fd = extType.Descriptor()
187 }
Herbie Onge52379a2019-03-15 18:00:19 -0700188 } else {
189 // The name can either be the JSON name or the proto field name.
190 fd = fieldDescs.ByJSONName(name)
191 if fd == nil {
192 fd = fieldDescs.ByName(pref.Name(name))
193 }
Joe Tsaid47ea192019-07-09 22:38:15 -0700194 if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
195 fd = nil // reset since the weak reference is not linked in
196 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800197 }
198
199 if fd == nil {
200 // Field is unknown.
Herbie Ong4f0be712019-04-25 17:57:12 -0700201 if o.DiscardUnknown {
Damien Neil8c86fc52019-06-19 09:28:29 -0700202 if err := skipJSONValue(o.decoder); err != nil {
Herbie Ong4f0be712019-04-25 17:57:12 -0700203 return err
204 }
205 continue
206 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700207 return newError("%v contains unknown field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800208 }
209
210 // Do not allow duplicate fields.
211 num := uint64(fd.Number())
212 if seenNums.Has(num) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700213 return newError("%v contains repeated field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800214 }
215 seenNums.Set(num)
216
Herbie Onge63c4c42019-03-22 22:20:22 -0700217 // No need to set values for JSON null unless the field type is
Herbie Ong300b9fe2019-03-29 15:42:20 -0700218 // google.protobuf.Value or google.protobuf.NullValue.
219 if o.decoder.Peek() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700220 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800221 continue
222 }
223
Joe Tsaiac31a352019-05-13 14:32:56 -0700224 switch {
225 case fd.IsList():
Joe Tsai378c1322019-04-25 23:48:08 -0700226 list := m.Mutable(fd).List()
Damien Neil8c86fc52019-06-19 09:28:29 -0700227 if err := o.unmarshalList(list, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800228 return errors.New("%v|%q: %v", fd.FullName(), name, err)
229 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700230 case fd.IsMap():
Joe Tsai378c1322019-04-25 23:48:08 -0700231 mmap := m.Mutable(fd).Map()
Damien Neil8c86fc52019-06-19 09:28:29 -0700232 if err := o.unmarshalMap(mmap, fd); err != nil {
Joe Tsaiac31a352019-05-13 14:32:56 -0700233 return errors.New("%v|%q: %v", fd.FullName(), name, err)
234 }
235 default:
Herbie Ong8a1d4602019-04-02 20:19:36 -0700236 // If field is a oneof, check if it has already been set.
Joe Tsaiac31a352019-05-13 14:32:56 -0700237 if od := fd.ContainingOneof(); od != nil {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700238 idx := uint64(od.Index())
239 if seenOneofs.Has(idx) {
240 return errors.New("%v: oneof is already set", od.FullName())
241 }
242 seenOneofs.Set(idx)
243 }
244
Herbie Ongc96a79d2019-03-08 10:49:17 -0800245 // Required or optional fields.
Damien Neil8c86fc52019-06-19 09:28:29 -0700246 if err := o.unmarshalSingular(m, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800247 return errors.New("%v|%q: %v", fd.FullName(), name, err)
248 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800249 }
250 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800251}
252
Herbie Onge52379a2019-03-15 18:00:19 -0700253// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700254func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
255 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700256 if err == nil {
257 return xt, nil
258 }
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700259 return messageset.FindMessageSetExtension(o.Resolver, xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700260}
261
Herbie Ong300b9fe2019-03-29 15:42:20 -0700262func isKnownValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700263 md := fd.Message()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700264 return md != nil && md.FullName() == "google.protobuf.Value"
265}
266
267func isNullValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700268 ed := fd.Enum()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700269 return ed != nil && ed.FullName() == "google.protobuf.NullValue"
270}
271
Herbie Ongc96a79d2019-03-08 10:49:17 -0800272// unmarshalSingular unmarshals to the non-repeated field specified by the given
273// FieldDescriptor.
Joe Tsai378c1322019-04-25 23:48:08 -0700274func (o UnmarshalOptions) unmarshalSingular(m pref.Message, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800275 var val pref.Value
276 var err error
Herbie Ongc96a79d2019-03-08 10:49:17 -0800277 switch fd.Kind() {
278 case pref.MessageKind, pref.GroupKind:
Joe Tsai378c1322019-04-25 23:48:08 -0700279 m2 := m.NewMessage(fd)
280 err = o.unmarshalMessage(m2, false)
281 val = pref.ValueOf(m2)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800282 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700283 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800284 }
285
Damien Neil8c86fc52019-06-19 09:28:29 -0700286 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800287 return err
288 }
Joe Tsai378c1322019-04-25 23:48:08 -0700289 m.Set(fd, val)
Damien Neil8c86fc52019-06-19 09:28:29 -0700290 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800291}
292
293// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
294// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700295func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800296 const b32 int = 32
297 const b64 int = 64
298
Herbie Ong822de2d2019-03-27 13:16:23 -0700299 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700300 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800301 return pref.Value{}, err
302 }
303
304 kind := fd.Kind()
305 switch kind {
306 case pref.BoolKind:
307 return unmarshalBool(jval)
308
309 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
310 return unmarshalInt(jval, b32)
311
312 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
313 return unmarshalInt(jval, b64)
314
315 case pref.Uint32Kind, pref.Fixed32Kind:
316 return unmarshalUint(jval, b32)
317
318 case pref.Uint64Kind, pref.Fixed64Kind:
319 return unmarshalUint(jval, b64)
320
321 case pref.FloatKind:
322 return unmarshalFloat(jval, b32)
323
324 case pref.DoubleKind:
325 return unmarshalFloat(jval, b64)
326
327 case pref.StringKind:
328 pval, err := unmarshalString(jval)
Damien Neil8c86fc52019-06-19 09:28:29 -0700329 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800330 return pval, err
331 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700332 return pval, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800333
334 case pref.BytesKind:
335 return unmarshalBytes(jval)
336
337 case pref.EnumKind:
338 return unmarshalEnum(jval, fd)
339 }
340
341 panic(fmt.Sprintf("invalid scalar kind %v", kind))
342}
343
344func unmarshalBool(jval json.Value) (pref.Value, error) {
345 if jval.Type() != json.Bool {
346 return pref.Value{}, unexpectedJSONError{jval}
347 }
348 b, err := jval.Bool()
349 return pref.ValueOf(b), err
350}
351
352func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
353 switch jval.Type() {
354 case json.Number:
355 return getInt(jval, bitSize)
356
357 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700358 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700359 s := strings.TrimSpace(jval.String())
360 if len(s) != len(jval.String()) {
361 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
362 }
363 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800364 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700365 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800366 return pref.Value{}, err
367 }
368 return getInt(jval, bitSize)
369 }
370 return pref.Value{}, unexpectedJSONError{jval}
371}
372
373func getInt(jval json.Value, bitSize int) (pref.Value, error) {
374 n, err := jval.Int(bitSize)
375 if err != nil {
376 return pref.Value{}, err
377 }
378 if bitSize == 32 {
379 return pref.ValueOf(int32(n)), nil
380 }
381 return pref.ValueOf(n), nil
382}
383
384func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
385 switch jval.Type() {
386 case json.Number:
387 return getUint(jval, bitSize)
388
389 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700390 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700391 s := strings.TrimSpace(jval.String())
392 if len(s) != len(jval.String()) {
393 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
394 }
395 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800396 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700397 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800398 return pref.Value{}, err
399 }
400 return getUint(jval, bitSize)
401 }
402 return pref.Value{}, unexpectedJSONError{jval}
403}
404
405func getUint(jval json.Value, bitSize int) (pref.Value, error) {
406 n, err := jval.Uint(bitSize)
407 if err != nil {
408 return pref.Value{}, err
409 }
410 if bitSize == 32 {
411 return pref.ValueOf(uint32(n)), nil
412 }
413 return pref.ValueOf(n), nil
414}
415
416func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
417 switch jval.Type() {
418 case json.Number:
419 return getFloat(jval, bitSize)
420
421 case json.String:
422 s := jval.String()
423 switch s {
424 case "NaN":
425 if bitSize == 32 {
426 return pref.ValueOf(float32(math.NaN())), nil
427 }
428 return pref.ValueOf(math.NaN()), nil
429 case "Infinity":
430 if bitSize == 32 {
431 return pref.ValueOf(float32(math.Inf(+1))), nil
432 }
433 return pref.ValueOf(math.Inf(+1)), nil
434 case "-Infinity":
435 if bitSize == 32 {
436 return pref.ValueOf(float32(math.Inf(-1))), nil
437 }
438 return pref.ValueOf(math.Inf(-1)), nil
439 }
Herbie Onge52379a2019-03-15 18:00:19 -0700440 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700441 if len(s) != len(strings.TrimSpace(s)) {
442 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
443 }
Herbie Onge52379a2019-03-15 18:00:19 -0700444 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800445 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700446 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800447 return pref.Value{}, err
448 }
449 return getFloat(jval, bitSize)
450 }
451 return pref.Value{}, unexpectedJSONError{jval}
452}
453
454func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
455 n, err := jval.Float(bitSize)
456 if err != nil {
457 return pref.Value{}, err
458 }
459 if bitSize == 32 {
460 return pref.ValueOf(float32(n)), nil
461 }
462 return pref.ValueOf(n), nil
463}
464
465func unmarshalString(jval json.Value) (pref.Value, error) {
466 if jval.Type() != json.String {
467 return pref.Value{}, unexpectedJSONError{jval}
468 }
469 return pref.ValueOf(jval.String()), nil
470}
471
472func unmarshalBytes(jval json.Value) (pref.Value, error) {
473 if jval.Type() != json.String {
474 return pref.Value{}, unexpectedJSONError{jval}
475 }
476
477 s := jval.String()
478 enc := base64.StdEncoding
479 if strings.ContainsAny(s, "-_") {
480 enc = base64.URLEncoding
481 }
482 if len(s)%4 != 0 {
483 enc = enc.WithPadding(base64.NoPadding)
484 }
485 b, err := enc.DecodeString(s)
486 if err != nil {
487 return pref.Value{}, err
488 }
489 return pref.ValueOf(b), nil
490}
491
492func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
493 switch jval.Type() {
494 case json.String:
495 // Lookup EnumNumber based on name.
496 s := jval.String()
Joe Tsaid24bc722019-04-15 23:39:09 -0700497 if enumVal := fd.Enum().Values().ByName(pref.Name(s)); enumVal != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800498 return pref.ValueOf(enumVal.Number()), nil
499 }
500 return pref.Value{}, newError("invalid enum value %q", jval)
501
502 case json.Number:
503 n, err := jval.Int(32)
504 if err != nil {
505 return pref.Value{}, err
506 }
507 return pref.ValueOf(pref.EnumNumber(n)), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700508
509 case json.Null:
510 // This is only valid for google.protobuf.NullValue.
511 if isNullValue(fd) {
512 return pref.ValueOf(pref.EnumNumber(0)), nil
513 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800514 }
515
516 return pref.Value{}, unexpectedJSONError{jval}
517}
518
Herbie Ong822de2d2019-03-27 13:16:23 -0700519func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700520 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700521 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800522 return err
523 }
524 if jval.Type() != json.StartArray {
525 return unexpectedJSONError{jval}
526 }
527
528 switch fd.Kind() {
529 case pref.MessageKind, pref.GroupKind:
530 for {
531 m := list.NewMessage()
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700532 err := o.unmarshalMessage(m, false)
Damien Neil8c86fc52019-06-19 09:28:29 -0700533 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800534 if e, ok := err.(unexpectedJSONError); ok {
535 if e.value.Type() == json.EndArray {
536 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700537 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800538 }
539 }
540 return err
541 }
542 list.Append(pref.ValueOf(m))
543 }
544 default:
545 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700546 val, err := o.unmarshalScalar(fd)
Damien Neil8c86fc52019-06-19 09:28:29 -0700547 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800548 if e, ok := err.(unexpectedJSONError); ok {
549 if e.value.Type() == json.EndArray {
550 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700551 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800552 }
553 }
554 return err
555 }
556 list.Append(val)
557 }
558 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700559 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800560}
561
Herbie Ong822de2d2019-03-27 13:16:23 -0700562func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700563 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700564 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800565 return err
566 }
567 if jval.Type() != json.StartObject {
568 return unexpectedJSONError{jval}
569 }
570
Herbie Ongc96a79d2019-03-08 10:49:17 -0800571 // Determine ahead whether map entry is a scalar type or a message type in
572 // order to call the appropriate unmarshalMapValue func inside the for loop
573 // below.
Joe Tsaiac31a352019-05-13 14:32:56 -0700574 var unmarshalMapValue func() (pref.Value, error)
575 switch fd.MapValue().Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800576 case pref.MessageKind, pref.GroupKind:
577 unmarshalMapValue = func() (pref.Value, error) {
578 m := mmap.NewMessage()
Damien Neil8c86fc52019-06-19 09:28:29 -0700579 if err := o.unmarshalMessage(m, false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800580 return pref.Value{}, err
581 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700582 return pref.ValueOf(m), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800583 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700584 default:
585 unmarshalMapValue = func() (pref.Value, error) {
586 return o.unmarshalScalar(fd.MapValue())
587 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800588 }
589
590Loop:
591 for {
592 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700593 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700594 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800595 return err
596 }
597 switch jval.Type() {
598 default:
599 return unexpectedJSONError{jval}
600 case json.EndObject:
601 break Loop
602 case json.Name:
603 // Continue.
604 }
605
606 name, err := jval.Name()
Damien Neil8c86fc52019-06-19 09:28:29 -0700607 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800608 return err
609 }
610
611 // Unmarshal field name.
Joe Tsaiac31a352019-05-13 14:32:56 -0700612 pkey, err := unmarshalMapKey(name, fd.MapKey())
Damien Neil8c86fc52019-06-19 09:28:29 -0700613 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800614 return err
615 }
616
617 // Check for duplicate field name.
618 if mmap.Has(pkey) {
619 return newError("duplicate map key %q", jval)
620 }
621
622 // Read and unmarshal field value.
623 pval, err := unmarshalMapValue()
Damien Neil8c86fc52019-06-19 09:28:29 -0700624 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800625 return err
626 }
627
628 mmap.Set(pkey, pval)
629 }
630
Damien Neil8c86fc52019-06-19 09:28:29 -0700631 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800632}
633
634// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
635// integral or string type.
636func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
637 const b32 = 32
638 const b64 = 64
639 const base10 = 10
640
641 kind := fd.Kind()
642 switch kind {
643 case pref.StringKind:
644 return pref.ValueOf(name).MapKey(), nil
645
646 case pref.BoolKind:
647 switch name {
648 case "true":
649 return pref.ValueOf(true).MapKey(), nil
650 case "false":
651 return pref.ValueOf(false).MapKey(), nil
652 }
653 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
654
655 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
656 n, err := strconv.ParseInt(name, base10, b32)
657 if err != nil {
658 return pref.MapKey{}, err
659 }
660 return pref.ValueOf(int32(n)).MapKey(), nil
661
662 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
663 n, err := strconv.ParseInt(name, base10, b64)
664 if err != nil {
665 return pref.MapKey{}, err
666 }
667 return pref.ValueOf(int64(n)).MapKey(), nil
668
669 case pref.Uint32Kind, pref.Fixed32Kind:
670 n, err := strconv.ParseUint(name, base10, b32)
671 if err != nil {
672 return pref.MapKey{}, err
673 }
674 return pref.ValueOf(uint32(n)).MapKey(), nil
675
676 case pref.Uint64Kind, pref.Fixed64Kind:
677 n, err := strconv.ParseUint(name, base10, b64)
678 if err != nil {
679 return pref.MapKey{}, err
680 }
681 return pref.ValueOf(uint64(n)).MapKey(), nil
682 }
683
684 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
685}