blob: cb4f7fbc8220c3097460cb94ea71be9fc9428dcc [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 {
Damien Neil79bfdbe2019-08-28 11:08:22 -0700186 fd = extType.TypeDescriptor()
Joe Tsai0bf41132019-09-05 21:46:36 -0700187 if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() {
188 return errors.New("message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName())
189 }
Damien Neil92f76182019-08-02 16:58:08 -0700190 }
Herbie Onge52379a2019-03-15 18:00:19 -0700191 } else {
192 // The name can either be the JSON name or the proto field name.
193 fd = fieldDescs.ByJSONName(name)
194 if fd == nil {
195 fd = fieldDescs.ByName(pref.Name(name))
196 }
Joe Tsaid47ea192019-07-09 22:38:15 -0700197 if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
198 fd = nil // reset since the weak reference is not linked in
199 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800200 }
201
202 if fd == nil {
203 // Field is unknown.
Herbie Ong4f0be712019-04-25 17:57:12 -0700204 if o.DiscardUnknown {
Damien Neil8c86fc52019-06-19 09:28:29 -0700205 if err := skipJSONValue(o.decoder); err != nil {
Herbie Ong4f0be712019-04-25 17:57:12 -0700206 return err
207 }
208 continue
209 }
Joe Tsai0fc49f82019-05-01 12:29:25 -0700210 return newError("%v contains unknown field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800211 }
212
213 // Do not allow duplicate fields.
214 num := uint64(fd.Number())
215 if seenNums.Has(num) {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700216 return newError("%v contains repeated field %s", messageDesc.FullName(), jval)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800217 }
218 seenNums.Set(num)
219
Herbie Onge63c4c42019-03-22 22:20:22 -0700220 // No need to set values for JSON null unless the field type is
Herbie Ong300b9fe2019-03-29 15:42:20 -0700221 // google.protobuf.Value or google.protobuf.NullValue.
222 if o.decoder.Peek() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700223 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800224 continue
225 }
226
Joe Tsaiac31a352019-05-13 14:32:56 -0700227 switch {
228 case fd.IsList():
Joe Tsai378c1322019-04-25 23:48:08 -0700229 list := m.Mutable(fd).List()
Damien Neil8c86fc52019-06-19 09:28:29 -0700230 if err := o.unmarshalList(list, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800231 return errors.New("%v|%q: %v", fd.FullName(), name, err)
232 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700233 case fd.IsMap():
Joe Tsai378c1322019-04-25 23:48:08 -0700234 mmap := m.Mutable(fd).Map()
Damien Neil8c86fc52019-06-19 09:28:29 -0700235 if err := o.unmarshalMap(mmap, fd); err != nil {
Joe Tsaiac31a352019-05-13 14:32:56 -0700236 return errors.New("%v|%q: %v", fd.FullName(), name, err)
237 }
238 default:
Herbie Ong8a1d4602019-04-02 20:19:36 -0700239 // If field is a oneof, check if it has already been set.
Joe Tsaiac31a352019-05-13 14:32:56 -0700240 if od := fd.ContainingOneof(); od != nil {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700241 idx := uint64(od.Index())
242 if seenOneofs.Has(idx) {
243 return errors.New("%v: oneof is already set", od.FullName())
244 }
245 seenOneofs.Set(idx)
246 }
247
Herbie Ongc96a79d2019-03-08 10:49:17 -0800248 // Required or optional fields.
Damien Neil8c86fc52019-06-19 09:28:29 -0700249 if err := o.unmarshalSingular(m, fd); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800250 return errors.New("%v|%q: %v", fd.FullName(), name, err)
251 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800252 }
253 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800254}
255
Herbie Onge52379a2019-03-15 18:00:19 -0700256// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700257func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
258 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700259 if err == nil {
260 return xt, nil
261 }
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700262 return messageset.FindMessageSetExtension(o.Resolver, xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700263}
264
Herbie Ong300b9fe2019-03-29 15:42:20 -0700265func isKnownValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700266 md := fd.Message()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700267 return md != nil && md.FullName() == "google.protobuf.Value"
268}
269
270func isNullValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700271 ed := fd.Enum()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700272 return ed != nil && ed.FullName() == "google.protobuf.NullValue"
273}
274
Herbie Ongc96a79d2019-03-08 10:49:17 -0800275// unmarshalSingular unmarshals to the non-repeated field specified by the given
276// FieldDescriptor.
Joe Tsai378c1322019-04-25 23:48:08 -0700277func (o UnmarshalOptions) unmarshalSingular(m pref.Message, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800278 var val pref.Value
279 var err error
Herbie Ongc96a79d2019-03-08 10:49:17 -0800280 switch fd.Kind() {
281 case pref.MessageKind, pref.GroupKind:
Damien Neild91c4222019-09-04 10:46:00 -0700282 val = m.NewField(fd)
283 err = o.unmarshalMessage(val.Message(), false)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800284 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700285 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800286 }
287
Damien Neil8c86fc52019-06-19 09:28:29 -0700288 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800289 return err
290 }
Joe Tsai378c1322019-04-25 23:48:08 -0700291 m.Set(fd, val)
Damien Neil8c86fc52019-06-19 09:28:29 -0700292 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800293}
294
295// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
296// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700297func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800298 const b32 int = 32
299 const b64 int = 64
300
Herbie Ong822de2d2019-03-27 13:16:23 -0700301 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700302 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800303 return pref.Value{}, err
304 }
305
306 kind := fd.Kind()
307 switch kind {
308 case pref.BoolKind:
309 return unmarshalBool(jval)
310
311 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
312 return unmarshalInt(jval, b32)
313
314 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
315 return unmarshalInt(jval, b64)
316
317 case pref.Uint32Kind, pref.Fixed32Kind:
318 return unmarshalUint(jval, b32)
319
320 case pref.Uint64Kind, pref.Fixed64Kind:
321 return unmarshalUint(jval, b64)
322
323 case pref.FloatKind:
324 return unmarshalFloat(jval, b32)
325
326 case pref.DoubleKind:
327 return unmarshalFloat(jval, b64)
328
329 case pref.StringKind:
330 pval, err := unmarshalString(jval)
Damien Neil8c86fc52019-06-19 09:28:29 -0700331 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800332 return pval, err
333 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700334 return pval, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800335
336 case pref.BytesKind:
337 return unmarshalBytes(jval)
338
339 case pref.EnumKind:
340 return unmarshalEnum(jval, fd)
341 }
342
343 panic(fmt.Sprintf("invalid scalar kind %v", kind))
344}
345
346func unmarshalBool(jval json.Value) (pref.Value, error) {
347 if jval.Type() != json.Bool {
348 return pref.Value{}, unexpectedJSONError{jval}
349 }
350 b, err := jval.Bool()
351 return pref.ValueOf(b), err
352}
353
354func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
355 switch jval.Type() {
356 case json.Number:
357 return getInt(jval, bitSize)
358
359 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700360 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700361 s := strings.TrimSpace(jval.String())
362 if len(s) != len(jval.String()) {
363 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
364 }
365 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800366 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700367 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800368 return pref.Value{}, err
369 }
370 return getInt(jval, bitSize)
371 }
372 return pref.Value{}, unexpectedJSONError{jval}
373}
374
375func getInt(jval json.Value, bitSize int) (pref.Value, error) {
376 n, err := jval.Int(bitSize)
377 if err != nil {
378 return pref.Value{}, err
379 }
380 if bitSize == 32 {
381 return pref.ValueOf(int32(n)), nil
382 }
383 return pref.ValueOf(n), nil
384}
385
386func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
387 switch jval.Type() {
388 case json.Number:
389 return getUint(jval, bitSize)
390
391 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700392 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700393 s := strings.TrimSpace(jval.String())
394 if len(s) != len(jval.String()) {
395 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
396 }
397 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800398 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700399 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800400 return pref.Value{}, err
401 }
402 return getUint(jval, bitSize)
403 }
404 return pref.Value{}, unexpectedJSONError{jval}
405}
406
407func getUint(jval json.Value, bitSize int) (pref.Value, error) {
408 n, err := jval.Uint(bitSize)
409 if err != nil {
410 return pref.Value{}, err
411 }
412 if bitSize == 32 {
413 return pref.ValueOf(uint32(n)), nil
414 }
415 return pref.ValueOf(n), nil
416}
417
418func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
419 switch jval.Type() {
420 case json.Number:
421 return getFloat(jval, bitSize)
422
423 case json.String:
424 s := jval.String()
425 switch s {
426 case "NaN":
427 if bitSize == 32 {
428 return pref.ValueOf(float32(math.NaN())), nil
429 }
430 return pref.ValueOf(math.NaN()), nil
431 case "Infinity":
432 if bitSize == 32 {
433 return pref.ValueOf(float32(math.Inf(+1))), nil
434 }
435 return pref.ValueOf(math.Inf(+1)), nil
436 case "-Infinity":
437 if bitSize == 32 {
438 return pref.ValueOf(float32(math.Inf(-1))), nil
439 }
440 return pref.ValueOf(math.Inf(-1)), nil
441 }
Herbie Onge52379a2019-03-15 18:00:19 -0700442 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700443 if len(s) != len(strings.TrimSpace(s)) {
444 return pref.Value{}, errors.New("invalid number %v", jval.Raw())
445 }
Herbie Onge52379a2019-03-15 18:00:19 -0700446 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800447 jval, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700448 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800449 return pref.Value{}, err
450 }
451 return getFloat(jval, bitSize)
452 }
453 return pref.Value{}, unexpectedJSONError{jval}
454}
455
456func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
457 n, err := jval.Float(bitSize)
458 if err != nil {
459 return pref.Value{}, err
460 }
461 if bitSize == 32 {
462 return pref.ValueOf(float32(n)), nil
463 }
464 return pref.ValueOf(n), nil
465}
466
467func unmarshalString(jval json.Value) (pref.Value, error) {
468 if jval.Type() != json.String {
469 return pref.Value{}, unexpectedJSONError{jval}
470 }
471 return pref.ValueOf(jval.String()), nil
472}
473
474func unmarshalBytes(jval json.Value) (pref.Value, error) {
475 if jval.Type() != json.String {
476 return pref.Value{}, unexpectedJSONError{jval}
477 }
478
479 s := jval.String()
480 enc := base64.StdEncoding
481 if strings.ContainsAny(s, "-_") {
482 enc = base64.URLEncoding
483 }
484 if len(s)%4 != 0 {
485 enc = enc.WithPadding(base64.NoPadding)
486 }
487 b, err := enc.DecodeString(s)
488 if err != nil {
489 return pref.Value{}, err
490 }
491 return pref.ValueOf(b), nil
492}
493
494func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
495 switch jval.Type() {
496 case json.String:
497 // Lookup EnumNumber based on name.
498 s := jval.String()
Joe Tsaid24bc722019-04-15 23:39:09 -0700499 if enumVal := fd.Enum().Values().ByName(pref.Name(s)); enumVal != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800500 return pref.ValueOf(enumVal.Number()), nil
501 }
502 return pref.Value{}, newError("invalid enum value %q", jval)
503
504 case json.Number:
505 n, err := jval.Int(32)
506 if err != nil {
507 return pref.Value{}, err
508 }
509 return pref.ValueOf(pref.EnumNumber(n)), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700510
511 case json.Null:
512 // This is only valid for google.protobuf.NullValue.
513 if isNullValue(fd) {
514 return pref.ValueOf(pref.EnumNumber(0)), nil
515 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800516 }
517
518 return pref.Value{}, unexpectedJSONError{jval}
519}
520
Herbie Ong822de2d2019-03-27 13:16:23 -0700521func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700522 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700523 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800524 return err
525 }
526 if jval.Type() != json.StartArray {
527 return unexpectedJSONError{jval}
528 }
529
530 switch fd.Kind() {
531 case pref.MessageKind, pref.GroupKind:
532 for {
Damien Neild91c4222019-09-04 10:46:00 -0700533 val := list.NewElement()
534 err := o.unmarshalMessage(val.Message(), false)
Damien Neil8c86fc52019-06-19 09:28:29 -0700535 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800536 if e, ok := err.(unexpectedJSONError); ok {
537 if e.value.Type() == json.EndArray {
538 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700539 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800540 }
541 }
542 return err
543 }
Damien Neild91c4222019-09-04 10:46:00 -0700544 list.Append(val)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800545 }
546 default:
547 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700548 val, err := o.unmarshalScalar(fd)
Damien Neil8c86fc52019-06-19 09:28:29 -0700549 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800550 if e, ok := err.(unexpectedJSONError); ok {
551 if e.value.Type() == json.EndArray {
552 // Done with list.
Damien Neil8c86fc52019-06-19 09:28:29 -0700553 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800554 }
555 }
556 return err
557 }
558 list.Append(val)
559 }
560 }
Damien Neil8c86fc52019-06-19 09:28:29 -0700561 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800562}
563
Herbie Ong822de2d2019-03-27 13:16:23 -0700564func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ong822de2d2019-03-27 13:16:23 -0700565 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700566 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800567 return err
568 }
569 if jval.Type() != json.StartObject {
570 return unexpectedJSONError{jval}
571 }
572
Herbie Ongc96a79d2019-03-08 10:49:17 -0800573 // Determine ahead whether map entry is a scalar type or a message type in
574 // order to call the appropriate unmarshalMapValue func inside the for loop
575 // below.
Joe Tsaiac31a352019-05-13 14:32:56 -0700576 var unmarshalMapValue func() (pref.Value, error)
577 switch fd.MapValue().Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800578 case pref.MessageKind, pref.GroupKind:
579 unmarshalMapValue = func() (pref.Value, error) {
Damien Neild91c4222019-09-04 10:46:00 -0700580 val := mmap.NewValue()
581 if err := o.unmarshalMessage(val.Message(), false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800582 return pref.Value{}, err
583 }
Damien Neild91c4222019-09-04 10:46:00 -0700584 return val, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800585 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700586 default:
587 unmarshalMapValue = func() (pref.Value, error) {
588 return o.unmarshalScalar(fd.MapValue())
589 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800590 }
591
592Loop:
593 for {
594 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700595 jval, err := o.decoder.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700596 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800597 return err
598 }
599 switch jval.Type() {
600 default:
601 return unexpectedJSONError{jval}
602 case json.EndObject:
603 break Loop
604 case json.Name:
605 // Continue.
606 }
607
608 name, err := jval.Name()
Damien Neil8c86fc52019-06-19 09:28:29 -0700609 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800610 return err
611 }
612
613 // Unmarshal field name.
Joe Tsaiac31a352019-05-13 14:32:56 -0700614 pkey, err := unmarshalMapKey(name, fd.MapKey())
Damien Neil8c86fc52019-06-19 09:28:29 -0700615 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800616 return err
617 }
618
619 // Check for duplicate field name.
620 if mmap.Has(pkey) {
621 return newError("duplicate map key %q", jval)
622 }
623
624 // Read and unmarshal field value.
625 pval, err := unmarshalMapValue()
Damien Neil8c86fc52019-06-19 09:28:29 -0700626 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800627 return err
628 }
629
630 mmap.Set(pkey, pval)
631 }
632
Damien Neil8c86fc52019-06-19 09:28:29 -0700633 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800634}
635
636// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
637// integral or string type.
638func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
639 const b32 = 32
640 const b64 = 64
641 const base10 = 10
642
643 kind := fd.Kind()
644 switch kind {
645 case pref.StringKind:
646 return pref.ValueOf(name).MapKey(), nil
647
648 case pref.BoolKind:
649 switch name {
650 case "true":
651 return pref.ValueOf(true).MapKey(), nil
652 case "false":
653 return pref.ValueOf(false).MapKey(), nil
654 }
655 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
656
657 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
658 n, err := strconv.ParseInt(name, base10, b32)
659 if err != nil {
660 return pref.MapKey{}, err
661 }
662 return pref.ValueOf(int32(n)).MapKey(), nil
663
664 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
665 n, err := strconv.ParseInt(name, base10, b64)
666 if err != nil {
667 return pref.MapKey{}, err
668 }
669 return pref.ValueOf(int64(n)).MapKey(), nil
670
671 case pref.Uint32Kind, pref.Fixed32Kind:
672 n, err := strconv.ParseUint(name, base10, b32)
673 if err != nil {
674 return pref.MapKey{}, err
675 }
676 return pref.ValueOf(uint32(n)).MapKey(), nil
677
678 case pref.Uint64Kind, pref.Fixed64Kind:
679 n, err := strconv.ParseUint(name, base10, b64)
680 if err != nil {
681 return pref.MapKey{}, err
682 }
683 return pref.ValueOf(uint64(n)).MapKey(), nil
684 }
685
686 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
687}