blob: db8a3dfd76a8cd61c7a2ea7d08b5ca62f29eca2c [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 {
Joe Tsai378c1322019-04-25 23:48:08 -070057 proto.Reset(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -080058
Herbie Ong822de2d2019-03-27 13:16:23 -070059 if o.Resolver == nil {
60 o.Resolver = protoregistry.GlobalTypes
Herbie Onge52379a2019-03-15 18:00:19 -070061 }
Herbie Ong822de2d2019-03-27 13:16:23 -070062 o.decoder = json.NewDecoder(b)
Herbie Onge52379a2019-03-15 18:00:19 -070063
Damien Neil8c86fc52019-06-19 09:28:29 -070064 if err := o.unmarshalMessage(m.ProtoReflect(), false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -080065 return err
66 }
67
68 // Check for EOF.
Herbie Ong822de2d2019-03-27 13:16:23 -070069 val, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -080070 if err != nil {
71 return err
72 }
73 if val.Type() != json.EOF {
74 return unexpectedJSONError{val}
75 }
Damien Neil4686e232019-04-05 13:31:40 -070076
Damien Neil8c86fc52019-06-19 09:28:29 -070077 if o.AllowPartial {
78 return nil
Damien Neil4686e232019-04-05 13:31:40 -070079 }
Damien Neil8c86fc52019-06-19 09:28:29 -070080 return proto.IsInitialized(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -080081}
82
Herbie Ongc96a79d2019-03-08 10:49:17 -080083// unexpectedJSONError is an error that contains the unexpected json.Value. This
Herbie Ong822de2d2019-03-27 13:16:23 -070084// is returned by methods to provide callers the read json.Value that it did not
85// expect.
Herbie Ongc96a79d2019-03-08 10:49:17 -080086// TODO: Consider moving this to internal/encoding/json for consistency with
87// errors that package returns.
88type unexpectedJSONError struct {
89 value json.Value
90}
91
92func (e unexpectedJSONError) Error() string {
93 return newError("unexpected value %s", e.value).Error()
94}
95
96// newError returns an error object. If one of the values passed in is of
97// json.Value type, it produces an error with position info.
98func newError(f string, x ...interface{}) error {
99 var hasValue bool
100 var line, column int
101 for i := 0; i < len(x); i++ {
102 if val, ok := x[i].(json.Value); ok {
103 line, column = val.Position()
104 hasValue = true
105 break
106 }
107 }
108 e := errors.New(f, x...)
109 if hasValue {
110 return errors.New("(line %d:%d): %v", line, column, e)
111 }
112 return e
113}
114
Herbie Ongc96a79d2019-03-08 10:49:17 -0800115// unmarshalMessage unmarshals a message into the given protoreflect.Message.
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700116func (o UnmarshalOptions) unmarshalMessage(m pref.Message, skipTypeURL bool) error {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700117 if isCustomType(m.Descriptor().FullName()) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700118 return o.unmarshalCustomType(m)
Herbie Onge63c4c42019-03-22 22:20:22 -0700119 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800120
Herbie Ong822de2d2019-03-27 13:16:23 -0700121 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700122 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800123 return err
124 }
125 if jval.Type() != json.StartObject {
126 return unexpectedJSONError{jval}
127 }
128
Damien Neil8c86fc52019-06-19 09:28:29 -0700129 if err := o.unmarshalFields(m, skipTypeURL); err != nil {
Herbie Onge63c4c42019-03-22 22:20:22 -0700130 return err
131 }
132
Damien Neil8c86fc52019-06-19 09:28:29 -0700133 return nil
Herbie Onge63c4c42019-03-22 22:20:22 -0700134}
135
136// unmarshalFields unmarshals the fields into the given protoreflect.Message.
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700137func (o UnmarshalOptions) unmarshalFields(m pref.Message, skipTypeURL bool) error {
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700138 messageDesc := m.Descriptor()
Joe Tsai1799d112019-08-08 13:31:59 -0700139 if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) {
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700140 return errors.New("no support for proto1 MessageSets")
141 }
142
Herbie Onge63c4c42019-03-22 22:20:22 -0700143 var seenNums set.Ints
Herbie Ong8a1d4602019-04-02 20:19:36 -0700144 var seenOneofs set.Ints
Joe Tsai0fc49f82019-05-01 12:29:25 -0700145 fieldDescs := messageDesc.Fields()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800146 for {
147 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700148 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700149 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800150 return err
151 }
152 switch jval.Type() {
153 default:
154 return unexpectedJSONError{jval}
155 case json.EndObject:
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700156 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800157 case json.Name:
158 // Continue below.
159 }
160
161 name, err := jval.Name()
Damien Neil8c86fc52019-06-19 09:28:29 -0700162 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800163 return err
164 }
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700165 // Unmarshaling a non-custom embedded message in Any will contain the
166 // JSON field "@type" which should be skipped because it is not a field
167 // of the embedded message, but simply an artifact of the Any format.
168 if skipTypeURL && name == "@type" {
169 o.decoder.Read()
170 continue
171 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800172
Herbie Onge52379a2019-03-15 18:00:19 -0700173 // Get the FieldDescriptor.
174 var fd pref.FieldDescriptor
175 if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
176 // Only extension names are in [name] format.
Joe Tsai378c1322019-04-25 23:48:08 -0700177 extName := pref.FullName(name[1 : len(name)-1])
178 extType, err := o.findExtension(extName)
179 if err != nil && err != protoregistry.NotFound {
180 return errors.New("unable to resolve [%v]: %v", extName, err)
Herbie Onge52379a2019-03-15 18:00:19 -0700181 }
Damien Neil92f76182019-08-02 16:58:08 -0700182 if extType != nil {
Damien Neil79bfdbe2019-08-28 11:08:22 -0700183 fd = extType.TypeDescriptor()
Joe Tsai0bf41132019-09-05 21:46:36 -0700184 if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() {
185 return errors.New("message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName())
186 }
Damien Neil92f76182019-08-02 16:58:08 -0700187 }
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))
Joe Tsai7fa1ee52019-09-15 00:32:55 -0700193 if fd == nil {
194 // The proto name of a group field is in all lowercase,
195 // while the textual field name is the group message name.
196 gd := fieldDescs.ByName(pref.Name(strings.ToLower(name)))
197 if gd != nil && gd.Kind() == pref.GroupKind && gd.Message().Name() == pref.Name(name) {
198 fd = gd
199 }
200 } else if fd.Kind() == pref.GroupKind && fd.Message().Name() != pref.Name(name) {
201 fd = nil // reset since field name is actually the message name
202 }
Herbie Onge52379a2019-03-15 18:00:19 -0700203 }
Joe Tsai6e095992019-08-10 13:56:36 -0700204 }
205 if flags.ProtoLegacy {
Joe Tsaid47ea192019-07-09 22:38:15 -0700206 if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
207 fd = nil // reset since the weak reference is not linked in
208 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800209 }
210
211 if fd == nil {
212 // Field is unknown.
Herbie Ong4f0be712019-04-25 17:57:12 -0700213 if o.DiscardUnknown {
Damien Neil8c86fc52019-06-19 09:28:29 -0700214 if err := skipJSONValue(o.decoder); err != nil {
Herbie Ong4f0be712019-04-25 17:57:12 -0700215 return err
216 }
217 continue
218 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700219 return newError("%v contains unknown field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800220 }
221
222 // Do not allow duplicate fields.
223 num := uint64(fd.Number())
224 if seenNums.Has(num) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700225 return newError("%v contains repeated field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800226 }
227 seenNums.Set(num)
228
Herbie Onge63c4c42019-03-22 22:20:22 -0700229 // No need to set values for JSON null unless the field type is
Herbie Ong300b9fe2019-03-29 15:42:20 -0700230 // google.protobuf.Value or google.protobuf.NullValue.
231 if o.decoder.Peek() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700232 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800233 continue
234 }
235
Joe Tsaiac31a352019-05-13 14:32:56 -0700236 switch {
237 case fd.IsList():
Joe Tsai378c1322019-04-25 23:48:08 -0700238 list := m.Mutable(fd).List()
Damien Neil8c86fc52019-06-19 09:28:29 -0700239 if err := o.unmarshalList(list, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800240 return errors.New("%v|%q: %v", fd.FullName(), name, err)
241 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700242 case fd.IsMap():
Joe Tsai378c1322019-04-25 23:48:08 -0700243 mmap := m.Mutable(fd).Map()
Damien Neil8c86fc52019-06-19 09:28:29 -0700244 if err := o.unmarshalMap(mmap, fd); err != nil {
Joe Tsaiac31a352019-05-13 14:32:56 -0700245 return errors.New("%v|%q: %v", fd.FullName(), name, err)
246 }
247 default:
Herbie Ong8a1d4602019-04-02 20:19:36 -0700248 // If field is a oneof, check if it has already been set.
Joe Tsaiac31a352019-05-13 14:32:56 -0700249 if od := fd.ContainingOneof(); od != nil {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700250 idx := uint64(od.Index())
251 if seenOneofs.Has(idx) {
252 return errors.New("%v: oneof is already set", od.FullName())
253 }
254 seenOneofs.Set(idx)
255 }
256
Herbie Ongc96a79d2019-03-08 10:49:17 -0800257 // Required or optional fields.
Damien Neil8c86fc52019-06-19 09:28:29 -0700258 if err := o.unmarshalSingular(m, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800259 return errors.New("%v|%q: %v", fd.FullName(), name, err)
260 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800261 }
262 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800263}
264
Herbie Onge52379a2019-03-15 18:00:19 -0700265// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700266func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
267 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700268 if err == nil {
269 return xt, nil
270 }
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700271 return messageset.FindMessageSetExtension(o.Resolver, xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700272}
273
Herbie Ong300b9fe2019-03-29 15:42:20 -0700274func isKnownValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700275 md := fd.Message()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700276 return md != nil && md.FullName() == "google.protobuf.Value"
277}
278
279func isNullValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700280 ed := fd.Enum()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700281 return ed != nil && ed.FullName() == "google.protobuf.NullValue"
282}
283
Herbie Ongc96a79d2019-03-08 10:49:17 -0800284// unmarshalSingular unmarshals to the non-repeated field specified by the given
285// FieldDescriptor.
Joe Tsai378c1322019-04-25 23:48:08 -0700286func (o UnmarshalOptions) unmarshalSingular(m pref.Message, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800287 var val pref.Value
288 var err error
Herbie Ongc96a79d2019-03-08 10:49:17 -0800289 switch fd.Kind() {
290 case pref.MessageKind, pref.GroupKind:
Damien Neild91c4222019-09-04 10:46:00 -0700291 val = m.NewField(fd)
292 err = o.unmarshalMessage(val.Message(), false)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800293 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700294 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800295 }
296
Damien Neil8c86fc52019-06-19 09:28:29 -0700297 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800298 return err
299 }
Joe Tsai378c1322019-04-25 23:48:08 -0700300 m.Set(fd, val)
Damien Neil8c86fc52019-06-19 09:28:29 -0700301 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800302}
303
304// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
305// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700306func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800307 const b32 int = 32
308 const b64 int = 64
309
Herbie Ong822de2d2019-03-27 13:16:23 -0700310 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700311 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800312 return pref.Value{}, err
313 }
314
315 kind := fd.Kind()
316 switch kind {
317 case pref.BoolKind:
318 return unmarshalBool(jval)
319
320 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
321 return unmarshalInt(jval, b32)
322
323 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
324 return unmarshalInt(jval, b64)
325
326 case pref.Uint32Kind, pref.Fixed32Kind:
327 return unmarshalUint(jval, b32)
328
329 case pref.Uint64Kind, pref.Fixed64Kind:
330 return unmarshalUint(jval, b64)
331
332 case pref.FloatKind:
333 return unmarshalFloat(jval, b32)
334
335 case pref.DoubleKind:
336 return unmarshalFloat(jval, b64)
337
338 case pref.StringKind:
339 pval, err := unmarshalString(jval)
Damien Neil8c86fc52019-06-19 09:28:29 -0700340 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800341 return pval, err
342 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700343 return pval, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800344
345 case pref.BytesKind:
346 return unmarshalBytes(jval)
347
348 case pref.EnumKind:
349 return unmarshalEnum(jval, fd)
350 }
351
352 panic(fmt.Sprintf("invalid scalar kind %v", kind))
353}
354
355func unmarshalBool(jval json.Value) (pref.Value, error) {
356 if jval.Type() != json.Bool {
357 return pref.Value{}, unexpectedJSONError{jval}
358 }
359 b, err := jval.Bool()
Joe Tsai84177c92019-09-17 13:38:48 -0700360 return pref.ValueOfBool(b), err
Herbie Ongc96a79d2019-03-08 10:49:17 -0800361}
362
363func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
364 switch jval.Type() {
365 case json.Number:
366 return getInt(jval, bitSize)
367
368 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700369 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700370 s := strings.TrimSpace(jval.String())
371 if len(s) != len(jval.String()) {
372 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
373 }
374 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800375 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700376 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800377 return pref.Value{}, err
378 }
379 return getInt(jval, bitSize)
380 }
381 return pref.Value{}, unexpectedJSONError{jval}
382}
383
384func getInt(jval json.Value, bitSize int) (pref.Value, error) {
385 n, err := jval.Int(bitSize)
386 if err != nil {
387 return pref.Value{}, err
388 }
389 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700390 return pref.ValueOfInt32(int32(n)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800391 }
Joe Tsai84177c92019-09-17 13:38:48 -0700392 return pref.ValueOfInt64(n), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800393}
394
395func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
396 switch jval.Type() {
397 case json.Number:
398 return getUint(jval, bitSize)
399
400 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700401 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700402 s := strings.TrimSpace(jval.String())
403 if len(s) != len(jval.String()) {
404 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
405 }
406 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800407 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700408 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800409 return pref.Value{}, err
410 }
411 return getUint(jval, bitSize)
412 }
413 return pref.Value{}, unexpectedJSONError{jval}
414}
415
416func getUint(jval json.Value, bitSize int) (pref.Value, error) {
417 n, err := jval.Uint(bitSize)
418 if err != nil {
419 return pref.Value{}, err
420 }
421 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700422 return pref.ValueOfUint32(uint32(n)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800423 }
Joe Tsai84177c92019-09-17 13:38:48 -0700424 return pref.ValueOfUint64(n), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800425}
426
427func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
428 switch jval.Type() {
429 case json.Number:
430 return getFloat(jval, bitSize)
431
432 case json.String:
433 s := jval.String()
434 switch s {
435 case "NaN":
436 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700437 return pref.ValueOfFloat32(float32(math.NaN())), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800438 }
Joe Tsai84177c92019-09-17 13:38:48 -0700439 return pref.ValueOfFloat64(math.NaN()), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800440 case "Infinity":
441 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700442 return pref.ValueOfFloat32(float32(math.Inf(+1))), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800443 }
Joe Tsai84177c92019-09-17 13:38:48 -0700444 return pref.ValueOfFloat64(math.Inf(+1)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800445 case "-Infinity":
446 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700447 return pref.ValueOfFloat32(float32(math.Inf(-1))), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800448 }
Joe Tsai84177c92019-09-17 13:38:48 -0700449 return pref.ValueOfFloat64(math.Inf(-1)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800450 }
Herbie Onge52379a2019-03-15 18:00:19 -0700451 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700452 if len(s) != len(strings.TrimSpace(s)) {
453 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
454 }
Herbie Onge52379a2019-03-15 18:00:19 -0700455 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800456 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700457 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800458 return pref.Value{}, err
459 }
460 return getFloat(jval, bitSize)
461 }
462 return pref.Value{}, unexpectedJSONError{jval}
463}
464
465func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
466 n, err := jval.Float(bitSize)
467 if err != nil {
468 return pref.Value{}, err
469 }
470 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700471 return pref.ValueOfFloat32(float32(n)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800472 }
Joe Tsai84177c92019-09-17 13:38:48 -0700473 return pref.ValueOfFloat64(n), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800474}
475
476func unmarshalString(jval json.Value) (pref.Value, error) {
477 if jval.Type() != json.String {
478 return pref.Value{}, unexpectedJSONError{jval}
479 }
Joe Tsai84177c92019-09-17 13:38:48 -0700480 return pref.ValueOfString(jval.String()), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800481}
482
483func unmarshalBytes(jval json.Value) (pref.Value, error) {
484 if jval.Type() != json.String {
485 return pref.Value{}, unexpectedJSONError{jval}
486 }
487
488 s := jval.String()
489 enc := base64.StdEncoding
490 if strings.ContainsAny(s, "-_") {
491 enc = base64.URLEncoding
492 }
493 if len(s)%4 != 0 {
494 enc = enc.WithPadding(base64.NoPadding)
495 }
496 b, err := enc.DecodeString(s)
497 if err != nil {
498 return pref.Value{}, err
499 }
Joe Tsai84177c92019-09-17 13:38:48 -0700500 return pref.ValueOfBytes(b), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800501}
502
503func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
504 switch jval.Type() {
505 case json.String:
506 // Lookup EnumNumber based on name.
507 s := jval.String()
Joe Tsaid24bc722019-04-15 23:39:09 -0700508 if enumVal := fd.Enum().Values().ByName(pref.Name(s)); enumVal != nil {
Joe Tsai84177c92019-09-17 13:38:48 -0700509 return pref.ValueOfEnum(enumVal.Number()), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800510 }
511 return pref.Value{}, newError("invalid enum value %q", jval)
512
513 case json.Number:
514 n, err := jval.Int(32)
515 if err != nil {
516 return pref.Value{}, err
517 }
Joe Tsai84177c92019-09-17 13:38:48 -0700518 return pref.ValueOfEnum(pref.EnumNumber(n)), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700519
520 case json.Null:
521 // This is only valid for google.protobuf.NullValue.
522 if isNullValue(fd) {
Joe Tsai84177c92019-09-17 13:38:48 -0700523 return pref.ValueOfEnum(0), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700524 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800525 }
526
527 return pref.Value{}, unexpectedJSONError{jval}
528}
529
Herbie Ong822de2d2019-03-27 13:16:23 -0700530func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700531 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700532 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800533 return err
534 }
535 if jval.Type() != json.StartArray {
536 return unexpectedJSONError{jval}
537 }
538
539 switch fd.Kind() {
540 case pref.MessageKind, pref.GroupKind:
541 for {
Damien Neild91c4222019-09-04 10:46:00 -0700542 val := list.NewElement()
543 err := o.unmarshalMessage(val.Message(), false)
Damien Neil8c86fc52019-06-19 09:28:29 -0700544 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800545 if e, ok := err.(unexpectedJSONError); ok {
546 if e.value.Type() == json.EndArray {
547 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700548 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800549 }
550 }
551 return err
552 }
Damien Neild91c4222019-09-04 10:46:00 -0700553 list.Append(val)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800554 }
555 default:
556 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700557 val, err := o.unmarshalScalar(fd)
Damien Neil8c86fc52019-06-19 09:28:29 -0700558 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800559 if e, ok := err.(unexpectedJSONError); ok {
560 if e.value.Type() == json.EndArray {
561 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700562 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800563 }
564 }
565 return err
566 }
567 list.Append(val)
568 }
569 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700570 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800571}
572
Herbie Ong822de2d2019-03-27 13:16:23 -0700573func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700574 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700575 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800576 return err
577 }
578 if jval.Type() != json.StartObject {
579 return unexpectedJSONError{jval}
580 }
581
Herbie Ongc96a79d2019-03-08 10:49:17 -0800582 // Determine ahead whether map entry is a scalar type or a message type in
583 // order to call the appropriate unmarshalMapValue func inside the for loop
584 // below.
Joe Tsaiac31a352019-05-13 14:32:56 -0700585 var unmarshalMapValue func() (pref.Value, error)
586 switch fd.MapValue().Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800587 case pref.MessageKind, pref.GroupKind:
588 unmarshalMapValue = func() (pref.Value, error) {
Damien Neild91c4222019-09-04 10:46:00 -0700589 val := mmap.NewValue()
590 if err := o.unmarshalMessage(val.Message(), false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800591 return pref.Value{}, err
592 }
Damien Neild91c4222019-09-04 10:46:00 -0700593 return val, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800594 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700595 default:
596 unmarshalMapValue = func() (pref.Value, error) {
597 return o.unmarshalScalar(fd.MapValue())
598 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800599 }
600
601Loop:
602 for {
603 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700604 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700605 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800606 return err
607 }
608 switch jval.Type() {
609 default:
610 return unexpectedJSONError{jval}
611 case json.EndObject:
612 break Loop
613 case json.Name:
614 // Continue.
615 }
616
617 name, err := jval.Name()
Damien Neil8c86fc52019-06-19 09:28:29 -0700618 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800619 return err
620 }
621
622 // Unmarshal field name.
Joe Tsaiac31a352019-05-13 14:32:56 -0700623 pkey, err := unmarshalMapKey(name, fd.MapKey())
Damien Neil8c86fc52019-06-19 09:28:29 -0700624 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800625 return err
626 }
627
628 // Check for duplicate field name.
629 if mmap.Has(pkey) {
630 return newError("duplicate map key %q", jval)
631 }
632
633 // Read and unmarshal field value.
634 pval, err := unmarshalMapValue()
Damien Neil8c86fc52019-06-19 09:28:29 -0700635 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800636 return err
637 }
638
639 mmap.Set(pkey, pval)
640 }
641
Damien Neil8c86fc52019-06-19 09:28:29 -0700642 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800643}
644
645// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
646// integral or string type.
647func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
648 const b32 = 32
649 const b64 = 64
650 const base10 = 10
651
652 kind := fd.Kind()
653 switch kind {
654 case pref.StringKind:
Joe Tsai84177c92019-09-17 13:38:48 -0700655 return pref.ValueOfString(name).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800656
657 case pref.BoolKind:
658 switch name {
659 case "true":
Joe Tsai84177c92019-09-17 13:38:48 -0700660 return pref.ValueOfBool(true).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800661 case "false":
Joe Tsai84177c92019-09-17 13:38:48 -0700662 return pref.ValueOfBool(false).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800663 }
664 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
665
666 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
667 n, err := strconv.ParseInt(name, base10, b32)
668 if err != nil {
669 return pref.MapKey{}, err
670 }
Joe Tsai84177c92019-09-17 13:38:48 -0700671 return pref.ValueOfInt32(int32(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800672
673 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
674 n, err := strconv.ParseInt(name, base10, b64)
675 if err != nil {
676 return pref.MapKey{}, err
677 }
Joe Tsai84177c92019-09-17 13:38:48 -0700678 return pref.ValueOfInt64(int64(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800679
680 case pref.Uint32Kind, pref.Fixed32Kind:
681 n, err := strconv.ParseUint(name, base10, b32)
682 if err != nil {
683 return pref.MapKey{}, err
684 }
Joe Tsai84177c92019-09-17 13:38:48 -0700685 return pref.ValueOfUint32(uint32(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800686
687 case pref.Uint64Kind, pref.Fixed64Kind:
688 n, err := strconv.ParseUint(name, base10, b64)
689 if err != nil {
690 return pref.MapKey{}, err
691 }
Joe Tsai84177c92019-09-17 13:38:48 -0700692 return pref.ValueOfUint64(uint64(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800693 }
694
695 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
696}