blob: faa56b0611b236903eac448967ef33d206f871c1 [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 Tsaid47ea192019-07-09 22:38:15 -0700204 if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
205 fd = nil // reset since the weak reference is not linked in
206 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800207 }
208
209 if fd == nil {
210 // Field is unknown.
Herbie Ong4f0be712019-04-25 17:57:12 -0700211 if o.DiscardUnknown {
Damien Neil8c86fc52019-06-19 09:28:29 -0700212 if err := skipJSONValue(o.decoder); err != nil {
Herbie Ong4f0be712019-04-25 17:57:12 -0700213 return err
214 }
215 continue
216 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700217 return newError("%v contains unknown field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800218 }
219
220 // Do not allow duplicate fields.
221 num := uint64(fd.Number())
222 if seenNums.Has(num) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700223 return newError("%v contains repeated field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800224 }
225 seenNums.Set(num)
226
Herbie Onge63c4c42019-03-22 22:20:22 -0700227 // No need to set values for JSON null unless the field type is
Herbie Ong300b9fe2019-03-29 15:42:20 -0700228 // google.protobuf.Value or google.protobuf.NullValue.
229 if o.decoder.Peek() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700230 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800231 continue
232 }
233
Joe Tsaiac31a352019-05-13 14:32:56 -0700234 switch {
235 case fd.IsList():
Joe Tsai378c1322019-04-25 23:48:08 -0700236 list := m.Mutable(fd).List()
Damien Neil8c86fc52019-06-19 09:28:29 -0700237 if err := o.unmarshalList(list, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800238 return errors.New("%v|%q: %v", fd.FullName(), name, err)
239 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700240 case fd.IsMap():
Joe Tsai378c1322019-04-25 23:48:08 -0700241 mmap := m.Mutable(fd).Map()
Damien Neil8c86fc52019-06-19 09:28:29 -0700242 if err := o.unmarshalMap(mmap, fd); err != nil {
Joe Tsaiac31a352019-05-13 14:32:56 -0700243 return errors.New("%v|%q: %v", fd.FullName(), name, err)
244 }
245 default:
Herbie Ong8a1d4602019-04-02 20:19:36 -0700246 // If field is a oneof, check if it has already been set.
Joe Tsaiac31a352019-05-13 14:32:56 -0700247 if od := fd.ContainingOneof(); od != nil {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700248 idx := uint64(od.Index())
249 if seenOneofs.Has(idx) {
250 return errors.New("%v: oneof is already set", od.FullName())
251 }
252 seenOneofs.Set(idx)
253 }
254
Herbie Ongc96a79d2019-03-08 10:49:17 -0800255 // Required or optional fields.
Damien Neil8c86fc52019-06-19 09:28:29 -0700256 if err := o.unmarshalSingular(m, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800257 return errors.New("%v|%q: %v", fd.FullName(), name, err)
258 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800259 }
260 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800261}
262
Herbie Onge52379a2019-03-15 18:00:19 -0700263// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700264func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
265 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700266 if err == nil {
267 return xt, nil
268 }
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700269 return messageset.FindMessageSetExtension(o.Resolver, xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700270}
271
Herbie Ong300b9fe2019-03-29 15:42:20 -0700272func isKnownValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700273 md := fd.Message()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700274 return md != nil && md.FullName() == "google.protobuf.Value"
275}
276
277func isNullValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700278 ed := fd.Enum()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700279 return ed != nil && ed.FullName() == "google.protobuf.NullValue"
280}
281
Herbie Ongc96a79d2019-03-08 10:49:17 -0800282// unmarshalSingular unmarshals to the non-repeated field specified by the given
283// FieldDescriptor.
Joe Tsai378c1322019-04-25 23:48:08 -0700284func (o UnmarshalOptions) unmarshalSingular(m pref.Message, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800285 var val pref.Value
286 var err error
Herbie Ongc96a79d2019-03-08 10:49:17 -0800287 switch fd.Kind() {
288 case pref.MessageKind, pref.GroupKind:
Damien Neild91c4222019-09-04 10:46:00 -0700289 val = m.NewField(fd)
290 err = o.unmarshalMessage(val.Message(), false)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800291 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700292 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800293 }
294
Damien Neil8c86fc52019-06-19 09:28:29 -0700295 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800296 return err
297 }
Joe Tsai378c1322019-04-25 23:48:08 -0700298 m.Set(fd, val)
Damien Neil8c86fc52019-06-19 09:28:29 -0700299 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800300}
301
302// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
303// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700304func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800305 const b32 int = 32
306 const b64 int = 64
307
Herbie Ong822de2d2019-03-27 13:16:23 -0700308 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700309 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800310 return pref.Value{}, err
311 }
312
313 kind := fd.Kind()
314 switch kind {
315 case pref.BoolKind:
316 return unmarshalBool(jval)
317
318 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
319 return unmarshalInt(jval, b32)
320
321 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
322 return unmarshalInt(jval, b64)
323
324 case pref.Uint32Kind, pref.Fixed32Kind:
325 return unmarshalUint(jval, b32)
326
327 case pref.Uint64Kind, pref.Fixed64Kind:
328 return unmarshalUint(jval, b64)
329
330 case pref.FloatKind:
331 return unmarshalFloat(jval, b32)
332
333 case pref.DoubleKind:
334 return unmarshalFloat(jval, b64)
335
336 case pref.StringKind:
337 pval, err := unmarshalString(jval)
Damien Neil8c86fc52019-06-19 09:28:29 -0700338 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800339 return pval, err
340 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700341 return pval, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800342
343 case pref.BytesKind:
344 return unmarshalBytes(jval)
345
346 case pref.EnumKind:
347 return unmarshalEnum(jval, fd)
348 }
349
350 panic(fmt.Sprintf("invalid scalar kind %v", kind))
351}
352
353func unmarshalBool(jval json.Value) (pref.Value, error) {
354 if jval.Type() != json.Bool {
355 return pref.Value{}, unexpectedJSONError{jval}
356 }
357 b, err := jval.Bool()
Joe Tsai84177c92019-09-17 13:38:48 -0700358 return pref.ValueOfBool(b), err
Herbie Ongc96a79d2019-03-08 10:49:17 -0800359}
360
361func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
362 switch jval.Type() {
363 case json.Number:
364 return getInt(jval, bitSize)
365
366 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700367 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700368 s := strings.TrimSpace(jval.String())
369 if len(s) != len(jval.String()) {
370 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
371 }
372 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800373 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700374 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800375 return pref.Value{}, err
376 }
377 return getInt(jval, bitSize)
378 }
379 return pref.Value{}, unexpectedJSONError{jval}
380}
381
382func getInt(jval json.Value, bitSize int) (pref.Value, error) {
383 n, err := jval.Int(bitSize)
384 if err != nil {
385 return pref.Value{}, err
386 }
387 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700388 return pref.ValueOfInt32(int32(n)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800389 }
Joe Tsai84177c92019-09-17 13:38:48 -0700390 return pref.ValueOfInt64(n), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800391}
392
393func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
394 switch jval.Type() {
395 case json.Number:
396 return getUint(jval, bitSize)
397
398 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700399 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700400 s := strings.TrimSpace(jval.String())
401 if len(s) != len(jval.String()) {
402 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
403 }
404 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800405 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700406 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800407 return pref.Value{}, err
408 }
409 return getUint(jval, bitSize)
410 }
411 return pref.Value{}, unexpectedJSONError{jval}
412}
413
414func getUint(jval json.Value, bitSize int) (pref.Value, error) {
415 n, err := jval.Uint(bitSize)
416 if err != nil {
417 return pref.Value{}, err
418 }
419 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700420 return pref.ValueOfUint32(uint32(n)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800421 }
Joe Tsai84177c92019-09-17 13:38:48 -0700422 return pref.ValueOfUint64(n), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800423}
424
425func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
426 switch jval.Type() {
427 case json.Number:
428 return getFloat(jval, bitSize)
429
430 case json.String:
431 s := jval.String()
432 switch s {
433 case "NaN":
434 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700435 return pref.ValueOfFloat32(float32(math.NaN())), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800436 }
Joe Tsai84177c92019-09-17 13:38:48 -0700437 return pref.ValueOfFloat64(math.NaN()), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800438 case "Infinity":
439 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700440 return pref.ValueOfFloat32(float32(math.Inf(+1))), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800441 }
Joe Tsai84177c92019-09-17 13:38:48 -0700442 return pref.ValueOfFloat64(math.Inf(+1)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800443 case "-Infinity":
444 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700445 return pref.ValueOfFloat32(float32(math.Inf(-1))), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800446 }
Joe Tsai84177c92019-09-17 13:38:48 -0700447 return pref.ValueOfFloat64(math.Inf(-1)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800448 }
Herbie Onge52379a2019-03-15 18:00:19 -0700449 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700450 if len(s) != len(strings.TrimSpace(s)) {
451 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
452 }
Herbie Onge52379a2019-03-15 18:00:19 -0700453 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800454 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700455 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800456 return pref.Value{}, err
457 }
458 return getFloat(jval, bitSize)
459 }
460 return pref.Value{}, unexpectedJSONError{jval}
461}
462
463func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
464 n, err := jval.Float(bitSize)
465 if err != nil {
466 return pref.Value{}, err
467 }
468 if bitSize == 32 {
Joe Tsai84177c92019-09-17 13:38:48 -0700469 return pref.ValueOfFloat32(float32(n)), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800470 }
Joe Tsai84177c92019-09-17 13:38:48 -0700471 return pref.ValueOfFloat64(n), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800472}
473
474func unmarshalString(jval json.Value) (pref.Value, error) {
475 if jval.Type() != json.String {
476 return pref.Value{}, unexpectedJSONError{jval}
477 }
Joe Tsai84177c92019-09-17 13:38:48 -0700478 return pref.ValueOfString(jval.String()), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800479}
480
481func unmarshalBytes(jval json.Value) (pref.Value, error) {
482 if jval.Type() != json.String {
483 return pref.Value{}, unexpectedJSONError{jval}
484 }
485
486 s := jval.String()
487 enc := base64.StdEncoding
488 if strings.ContainsAny(s, "-_") {
489 enc = base64.URLEncoding
490 }
491 if len(s)%4 != 0 {
492 enc = enc.WithPadding(base64.NoPadding)
493 }
494 b, err := enc.DecodeString(s)
495 if err != nil {
496 return pref.Value{}, err
497 }
Joe Tsai84177c92019-09-17 13:38:48 -0700498 return pref.ValueOfBytes(b), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800499}
500
501func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
502 switch jval.Type() {
503 case json.String:
504 // Lookup EnumNumber based on name.
505 s := jval.String()
Joe Tsaid24bc722019-04-15 23:39:09 -0700506 if enumVal := fd.Enum().Values().ByName(pref.Name(s)); enumVal != nil {
Joe Tsai84177c92019-09-17 13:38:48 -0700507 return pref.ValueOfEnum(enumVal.Number()), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800508 }
509 return pref.Value{}, newError("invalid enum value %q", jval)
510
511 case json.Number:
512 n, err := jval.Int(32)
513 if err != nil {
514 return pref.Value{}, err
515 }
Joe Tsai84177c92019-09-17 13:38:48 -0700516 return pref.ValueOfEnum(pref.EnumNumber(n)), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700517
518 case json.Null:
519 // This is only valid for google.protobuf.NullValue.
520 if isNullValue(fd) {
Joe Tsai84177c92019-09-17 13:38:48 -0700521 return pref.ValueOfEnum(0), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700522 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800523 }
524
525 return pref.Value{}, unexpectedJSONError{jval}
526}
527
Herbie Ong822de2d2019-03-27 13:16:23 -0700528func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700529 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700530 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800531 return err
532 }
533 if jval.Type() != json.StartArray {
534 return unexpectedJSONError{jval}
535 }
536
537 switch fd.Kind() {
538 case pref.MessageKind, pref.GroupKind:
539 for {
Damien Neild91c4222019-09-04 10:46:00 -0700540 val := list.NewElement()
541 err := o.unmarshalMessage(val.Message(), false)
Damien Neil8c86fc52019-06-19 09:28:29 -0700542 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800543 if e, ok := err.(unexpectedJSONError); ok {
544 if e.value.Type() == json.EndArray {
545 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700546 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800547 }
548 }
549 return err
550 }
Damien Neild91c4222019-09-04 10:46:00 -0700551 list.Append(val)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800552 }
553 default:
554 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700555 val, err := o.unmarshalScalar(fd)
Damien Neil8c86fc52019-06-19 09:28:29 -0700556 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800557 if e, ok := err.(unexpectedJSONError); ok {
558 if e.value.Type() == json.EndArray {
559 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700560 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800561 }
562 }
563 return err
564 }
565 list.Append(val)
566 }
567 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700568 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800569}
570
Herbie Ong822de2d2019-03-27 13:16:23 -0700571func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700572 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700573 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800574 return err
575 }
576 if jval.Type() != json.StartObject {
577 return unexpectedJSONError{jval}
578 }
579
Herbie Ongc96a79d2019-03-08 10:49:17 -0800580 // Determine ahead whether map entry is a scalar type or a message type in
581 // order to call the appropriate unmarshalMapValue func inside the for loop
582 // below.
Joe Tsaiac31a352019-05-13 14:32:56 -0700583 var unmarshalMapValue func() (pref.Value, error)
584 switch fd.MapValue().Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800585 case pref.MessageKind, pref.GroupKind:
586 unmarshalMapValue = func() (pref.Value, error) {
Damien Neild91c4222019-09-04 10:46:00 -0700587 val := mmap.NewValue()
588 if err := o.unmarshalMessage(val.Message(), false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800589 return pref.Value{}, err
590 }
Damien Neild91c4222019-09-04 10:46:00 -0700591 return val, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800592 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700593 default:
594 unmarshalMapValue = func() (pref.Value, error) {
595 return o.unmarshalScalar(fd.MapValue())
596 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800597 }
598
599Loop:
600 for {
601 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700602 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700603 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800604 return err
605 }
606 switch jval.Type() {
607 default:
608 return unexpectedJSONError{jval}
609 case json.EndObject:
610 break Loop
611 case json.Name:
612 // Continue.
613 }
614
615 name, err := jval.Name()
Damien Neil8c86fc52019-06-19 09:28:29 -0700616 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800617 return err
618 }
619
620 // Unmarshal field name.
Joe Tsaiac31a352019-05-13 14:32:56 -0700621 pkey, err := unmarshalMapKey(name, fd.MapKey())
Damien Neil8c86fc52019-06-19 09:28:29 -0700622 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800623 return err
624 }
625
626 // Check for duplicate field name.
627 if mmap.Has(pkey) {
628 return newError("duplicate map key %q", jval)
629 }
630
631 // Read and unmarshal field value.
632 pval, err := unmarshalMapValue()
Damien Neil8c86fc52019-06-19 09:28:29 -0700633 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800634 return err
635 }
636
637 mmap.Set(pkey, pval)
638 }
639
Damien Neil8c86fc52019-06-19 09:28:29 -0700640 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800641}
642
643// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
644// integral or string type.
645func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
646 const b32 = 32
647 const b64 = 64
648 const base10 = 10
649
650 kind := fd.Kind()
651 switch kind {
652 case pref.StringKind:
Joe Tsai84177c92019-09-17 13:38:48 -0700653 return pref.ValueOfString(name).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800654
655 case pref.BoolKind:
656 switch name {
657 case "true":
Joe Tsai84177c92019-09-17 13:38:48 -0700658 return pref.ValueOfBool(true).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800659 case "false":
Joe Tsai84177c92019-09-17 13:38:48 -0700660 return pref.ValueOfBool(false).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800661 }
662 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
663
664 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
665 n, err := strconv.ParseInt(name, base10, b32)
666 if err != nil {
667 return pref.MapKey{}, err
668 }
Joe Tsai84177c92019-09-17 13:38:48 -0700669 return pref.ValueOfInt32(int32(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800670
671 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
672 n, err := strconv.ParseInt(name, base10, b64)
673 if err != nil {
674 return pref.MapKey{}, err
675 }
Joe Tsai84177c92019-09-17 13:38:48 -0700676 return pref.ValueOfInt64(int64(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800677
678 case pref.Uint32Kind, pref.Fixed32Kind:
679 n, err := strconv.ParseUint(name, base10, b32)
680 if err != nil {
681 return pref.MapKey{}, err
682 }
Joe Tsai84177c92019-09-17 13:38:48 -0700683 return pref.ValueOfUint32(uint32(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800684
685 case pref.Uint64Kind, pref.Fixed64Kind:
686 n, err := strconv.ParseUint(name, base10, b64)
687 if err != nil {
688 return pref.MapKey{}, err
689 }
Joe Tsai84177c92019-09-17 13:38:48 -0700690 return pref.ValueOfUint64(uint64(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800691 }
692
693 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
694}