blob: 4d13d777b058b453cd0ad016396e5092f0c22978 [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 Onge52379a2019-03-15 18:00:19 -070048}
Herbie Ongc96a79d2019-03-08 10:49:17 -080049
50// Unmarshal reads the given []byte and populates the given proto.Message using
51// options in UnmarshalOptions object. It will clear the message first before
52// setting the fields. If it returns an error, the given message may be
53// partially set.
Joe Tsaicdb77732019-05-14 16:05:06 -070054func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
Joe Tsai378c1322019-04-25 23:48:08 -070055 proto.Reset(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -080056
Herbie Ong822de2d2019-03-27 13:16:23 -070057 if o.Resolver == nil {
58 o.Resolver = protoregistry.GlobalTypes
Herbie Onge52379a2019-03-15 18:00:19 -070059 }
60
Herbie Ongd2ece132020-01-07 16:45:24 -080061 dec := decoder{json.NewDecoder(b), o}
62 if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -080063 return err
64 }
65
66 // Check for EOF.
Herbie Ongd2ece132020-01-07 16:45:24 -080067 tok, err := dec.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -080068 if err != nil {
69 return err
70 }
Herbie Ongd2ece132020-01-07 16:45:24 -080071 if tok.Kind() != json.EOF {
72 return dec.unexpectedTokenError(tok)
Herbie Ongc96a79d2019-03-08 10:49:17 -080073 }
Damien Neil4686e232019-04-05 13:31:40 -070074
Damien Neil8c86fc52019-06-19 09:28:29 -070075 if o.AllowPartial {
76 return nil
Damien Neil4686e232019-04-05 13:31:40 -070077 }
Damien Neil8c86fc52019-06-19 09:28:29 -070078 return proto.IsInitialized(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -080079}
80
Herbie Ongd2ece132020-01-07 16:45:24 -080081type decoder struct {
82 *json.Decoder
83 opts UnmarshalOptions
Herbie Ongc96a79d2019-03-08 10:49:17 -080084}
85
Herbie Ongd2ece132020-01-07 16:45:24 -080086// newError returns an error object with position info.
87func (d decoder) newError(pos int, f string, x ...interface{}) error {
88 line, column := d.Position(pos)
89 head := fmt.Sprintf("(line %d:%d): ", line, column)
90 return errors.New(head+f, x...)
Herbie Ongc96a79d2019-03-08 10:49:17 -080091}
92
Herbie Ongd2ece132020-01-07 16:45:24 -080093// unexpectedTokenError returns a syntax error for the given unexpected token.
94func (d decoder) unexpectedTokenError(tok json.Token) error {
95 return d.syntaxError(tok.Pos(), "unexpected token %s", tok.RawString())
96}
97
98// syntaxError returns a syntax error for given position.
99func (d decoder) syntaxError(pos int, f string, x ...interface{}) error {
100 line, column := d.Position(pos)
101 head := fmt.Sprintf("syntax error (line %d:%d): ", line, column)
102 return errors.New(head+f, x...)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800103}
104
Herbie Ongc96a79d2019-03-08 10:49:17 -0800105// unmarshalMessage unmarshals a message into the given protoreflect.Message.
Herbie Ongd2ece132020-01-07 16:45:24 -0800106func (d decoder) unmarshalMessage(m pref.Message, skipTypeURL bool) error {
Joe Tsai0fc49f82019-05-01 12:29:25 -0700107 if isCustomType(m.Descriptor().FullName()) {
Herbie Ongd2ece132020-01-07 16:45:24 -0800108 return d.unmarshalCustomType(m)
Herbie Onge63c4c42019-03-22 22:20:22 -0700109 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800110
Herbie Ongd2ece132020-01-07 16:45:24 -0800111 tok, err := d.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700112 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800113 return err
114 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800115 if tok.Kind() != json.ObjectOpen {
116 return d.unexpectedTokenError(tok)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800117 }
118
Herbie Ongd2ece132020-01-07 16:45:24 -0800119 if err := d.unmarshalFields(m, skipTypeURL); err != nil {
Herbie Onge63c4c42019-03-22 22:20:22 -0700120 return err
121 }
122
Damien Neil8c86fc52019-06-19 09:28:29 -0700123 return nil
Herbie Onge63c4c42019-03-22 22:20:22 -0700124}
125
126// unmarshalFields unmarshals the fields into the given protoreflect.Message.
Herbie Ongd2ece132020-01-07 16:45:24 -0800127func (d decoder) unmarshalFields(m pref.Message, skipTypeURL bool) error {
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700128 messageDesc := m.Descriptor()
Joe Tsai1799d112019-08-08 13:31:59 -0700129 if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) {
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700130 return errors.New("no support for proto1 MessageSets")
131 }
132
Herbie Onge63c4c42019-03-22 22:20:22 -0700133 var seenNums set.Ints
Herbie Ong8a1d4602019-04-02 20:19:36 -0700134 var seenOneofs set.Ints
Joe Tsai0fc49f82019-05-01 12:29:25 -0700135 fieldDescs := messageDesc.Fields()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800136 for {
137 // Read field name.
Herbie Ongd2ece132020-01-07 16:45:24 -0800138 tok, err := d.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700139 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800140 return err
141 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800142 switch tok.Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800143 default:
Herbie Ongd2ece132020-01-07 16:45:24 -0800144 return d.unexpectedTokenError(tok)
145 case json.ObjectClose:
Joe Tsai5ae10aa2019-07-11 18:23:08 -0700146 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800147 case json.Name:
148 // Continue below.
149 }
150
Herbie Ongd2ece132020-01-07 16:45:24 -0800151 name := tok.Name()
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700152 // Unmarshaling a non-custom embedded message in Any will contain the
153 // JSON field "@type" which should be skipped because it is not a field
154 // of the embedded message, but simply an artifact of the Any format.
155 if skipTypeURL && name == "@type" {
Herbie Ongd2ece132020-01-07 16:45:24 -0800156 d.Read()
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700157 continue
158 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800159
Herbie Onge52379a2019-03-15 18:00:19 -0700160 // Get the FieldDescriptor.
161 var fd pref.FieldDescriptor
162 if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
163 // Only extension names are in [name] format.
Joe Tsai378c1322019-04-25 23:48:08 -0700164 extName := pref.FullName(name[1 : len(name)-1])
Herbie Ongd2ece132020-01-07 16:45:24 -0800165 extType, err := d.findExtension(extName)
Joe Tsai378c1322019-04-25 23:48:08 -0700166 if err != nil && err != protoregistry.NotFound {
Herbie Ongd2ece132020-01-07 16:45:24 -0800167 return d.newError(tok.Pos(), "unable to resolve %s: %v", tok.RawString(), err)
Herbie Onge52379a2019-03-15 18:00:19 -0700168 }
Damien Neil92f76182019-08-02 16:58:08 -0700169 if extType != nil {
Damien Neil79bfdbe2019-08-28 11:08:22 -0700170 fd = extType.TypeDescriptor()
Joe Tsai0bf41132019-09-05 21:46:36 -0700171 if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() {
Herbie Ongd2ece132020-01-07 16:45:24 -0800172 return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName())
Joe Tsai0bf41132019-09-05 21:46:36 -0700173 }
Damien Neil92f76182019-08-02 16:58:08 -0700174 }
Herbie Onge52379a2019-03-15 18:00:19 -0700175 } else {
176 // The name can either be the JSON name or the proto field name.
177 fd = fieldDescs.ByJSONName(name)
178 if fd == nil {
179 fd = fieldDescs.ByName(pref.Name(name))
Joe Tsai7fa1ee52019-09-15 00:32:55 -0700180 if fd == nil {
181 // The proto name of a group field is in all lowercase,
182 // while the textual field name is the group message name.
183 gd := fieldDescs.ByName(pref.Name(strings.ToLower(name)))
184 if gd != nil && gd.Kind() == pref.GroupKind && gd.Message().Name() == pref.Name(name) {
185 fd = gd
186 }
187 } else if fd.Kind() == pref.GroupKind && fd.Message().Name() != pref.Name(name) {
188 fd = nil // reset since field name is actually the message name
189 }
Herbie Onge52379a2019-03-15 18:00:19 -0700190 }
Joe Tsai6e095992019-08-10 13:56:36 -0700191 }
192 if flags.ProtoLegacy {
Joe Tsaid47ea192019-07-09 22:38:15 -0700193 if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
194 fd = nil // reset since the weak reference is not linked in
195 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800196 }
197
198 if fd == nil {
199 // Field is unknown.
Herbie Ongd2ece132020-01-07 16:45:24 -0800200 if d.opts.DiscardUnknown {
201 if err := d.skipJSONValue(); err != nil {
Herbie Ong4f0be712019-04-25 17:57:12 -0700202 return err
203 }
204 continue
205 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800206 return d.newError(tok.Pos(), "unknown field %v", tok.RawString())
Herbie Ongc96a79d2019-03-08 10:49:17 -0800207 }
208
209 // Do not allow duplicate fields.
210 num := uint64(fd.Number())
211 if seenNums.Has(num) {
Herbie Ongd2ece132020-01-07 16:45:24 -0800212 return d.newError(tok.Pos(), "duplicate field %v", tok.RawString())
Herbie Ongc96a79d2019-03-08 10:49:17 -0800213 }
214 seenNums.Set(num)
215
Herbie Onge63c4c42019-03-22 22:20:22 -0700216 // No need to set values for JSON null unless the field type is
Herbie Ong300b9fe2019-03-29 15:42:20 -0700217 // google.protobuf.Value or google.protobuf.NullValue.
Herbie Ongd2ece132020-01-07 16:45:24 -0800218 if tok, _ := d.Peek(); tok.Kind() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
219 d.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800220 continue
221 }
222
Joe Tsaiac31a352019-05-13 14:32:56 -0700223 switch {
224 case fd.IsList():
Joe Tsai378c1322019-04-25 23:48:08 -0700225 list := m.Mutable(fd).List()
Herbie Ongd2ece132020-01-07 16:45:24 -0800226 if err := d.unmarshalList(list, fd); err != nil {
227 return err
Herbie Ongc96a79d2019-03-08 10:49:17 -0800228 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700229 case fd.IsMap():
Joe Tsai378c1322019-04-25 23:48:08 -0700230 mmap := m.Mutable(fd).Map()
Herbie Ongd2ece132020-01-07 16:45:24 -0800231 if err := d.unmarshalMap(mmap, fd); err != nil {
232 return err
Joe Tsaiac31a352019-05-13 14:32:56 -0700233 }
234 default:
Herbie Ong8a1d4602019-04-02 20:19:36 -0700235 // If field is a oneof, check if it has already been set.
Joe Tsaiac31a352019-05-13 14:32:56 -0700236 if od := fd.ContainingOneof(); od != nil {
Herbie Ong8a1d4602019-04-02 20:19:36 -0700237 idx := uint64(od.Index())
238 if seenOneofs.Has(idx) {
Herbie Ongd2ece132020-01-07 16:45:24 -0800239 return d.newError(tok.Pos(), "error parsing %s, oneof %v is already set", tok.RawString(), od.FullName())
Herbie Ong8a1d4602019-04-02 20:19:36 -0700240 }
241 seenOneofs.Set(idx)
242 }
243
Herbie Ongc96a79d2019-03-08 10:49:17 -0800244 // Required or optional fields.
Herbie Ongd2ece132020-01-07 16:45:24 -0800245 if err := d.unmarshalSingular(m, fd); err != nil {
246 return err
Herbie Ongc96a79d2019-03-08 10:49:17 -0800247 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800248 }
249 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800250}
251
Herbie Onge52379a2019-03-15 18:00:19 -0700252// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ongd2ece132020-01-07 16:45:24 -0800253func (d decoder) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
254 xt, err := d.opts.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700255 if err == nil {
256 return xt, nil
257 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800258 return messageset.FindMessageSetExtension(d.opts.Resolver, xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700259}
260
Herbie Ong300b9fe2019-03-29 15:42:20 -0700261func isKnownValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700262 md := fd.Message()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700263 return md != nil && md.FullName() == "google.protobuf.Value"
264}
265
266func isNullValue(fd pref.FieldDescriptor) bool {
Joe Tsaid24bc722019-04-15 23:39:09 -0700267 ed := fd.Enum()
Herbie Ong300b9fe2019-03-29 15:42:20 -0700268 return ed != nil && ed.FullName() == "google.protobuf.NullValue"
269}
270
Herbie Ongd2ece132020-01-07 16:45:24 -0800271// unmarshalSingular unmarshals to the non-repeated field specified
272// by the given FieldDescriptor.
273func (d decoder) unmarshalSingular(m pref.Message, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800274 var val pref.Value
275 var err error
Herbie Ongc96a79d2019-03-08 10:49:17 -0800276 switch fd.Kind() {
277 case pref.MessageKind, pref.GroupKind:
Damien Neild91c4222019-09-04 10:46:00 -0700278 val = m.NewField(fd)
Herbie Ongd2ece132020-01-07 16:45:24 -0800279 err = d.unmarshalMessage(val.Message(), false)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800280 default:
Herbie Ongd2ece132020-01-07 16:45:24 -0800281 val, err = d.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800282 }
283
Damien Neil8c86fc52019-06-19 09:28:29 -0700284 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800285 return err
286 }
Joe Tsai378c1322019-04-25 23:48:08 -0700287 m.Set(fd, val)
Damien Neil8c86fc52019-06-19 09:28:29 -0700288 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800289}
290
291// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
292// the given FieldDescriptor.
Herbie Ongd2ece132020-01-07 16:45:24 -0800293func (d decoder) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800294 const b32 int = 32
295 const b64 int = 64
296
Herbie Ongd2ece132020-01-07 16:45:24 -0800297 tok, err := d.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700298 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800299 return pref.Value{}, err
300 }
301
302 kind := fd.Kind()
303 switch kind {
304 case pref.BoolKind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800305 if tok.Kind() == json.Bool {
306 return pref.ValueOfBool(tok.Bool()), nil
307 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800308
309 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800310 if v, ok := unmarshalInt(tok, b32); ok {
311 return v, nil
312 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800313
314 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800315 if v, ok := unmarshalInt(tok, b64); ok {
316 return v, nil
317 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800318
319 case pref.Uint32Kind, pref.Fixed32Kind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800320 if v, ok := unmarshalUint(tok, b32); ok {
321 return v, nil
322 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800323
324 case pref.Uint64Kind, pref.Fixed64Kind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800325 if v, ok := unmarshalUint(tok, b64); ok {
326 return v, nil
327 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800328
329 case pref.FloatKind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800330 if v, ok := unmarshalFloat(tok, b32); ok {
331 return v, nil
332 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800333
334 case pref.DoubleKind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800335 if v, ok := unmarshalFloat(tok, b64); ok {
336 return v, nil
337 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800338
339 case pref.StringKind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800340 if tok.Kind() == json.String {
341 return pref.ValueOfString(tok.ParsedString()), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800342 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800343
344 case pref.BytesKind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800345 if v, ok := unmarshalBytes(tok); ok {
346 return v, nil
347 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800348
349 case pref.EnumKind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800350 if v, ok := unmarshalEnum(tok, fd); ok {
351 return v, nil
352 }
353
354 default:
355 panic(fmt.Sprintf("unmarshalScalar: invalid scalar kind %v", kind))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800356 }
357
Herbie Ongd2ece132020-01-07 16:45:24 -0800358 return pref.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString())
Herbie Ongc96a79d2019-03-08 10:49:17 -0800359}
360
Herbie Ongd2ece132020-01-07 16:45:24 -0800361func unmarshalInt(tok json.Token, bitSize int) (pref.Value, bool) {
362 switch tok.Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800363 case json.Number:
Herbie Ongd2ece132020-01-07 16:45:24 -0800364 return getInt(tok, bitSize)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800365
366 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700367 // Decode number from string.
Herbie Ongd2ece132020-01-07 16:45:24 -0800368 s := strings.TrimSpace(tok.ParsedString())
369 if len(s) != len(tok.ParsedString()) {
370 return pref.Value{}, false
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700371 }
372 dec := json.NewDecoder([]byte(s))
Herbie Ongd2ece132020-01-07 16:45:24 -0800373 tok, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700374 if err != nil {
Herbie Ongd2ece132020-01-07 16:45:24 -0800375 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800376 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800377 return getInt(tok, bitSize)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800378 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800379 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800380}
381
Herbie Ongd2ece132020-01-07 16:45:24 -0800382func getInt(tok json.Token, bitSize int) (pref.Value, bool) {
383 n, ok := tok.Int(bitSize)
384 if !ok {
385 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800386 }
387 if bitSize == 32 {
Herbie Ongd2ece132020-01-07 16:45:24 -0800388 return pref.ValueOfInt32(int32(n)), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800389 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800390 return pref.ValueOfInt64(n), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800391}
392
Herbie Ongd2ece132020-01-07 16:45:24 -0800393func unmarshalUint(tok json.Token, bitSize int) (pref.Value, bool) {
394 switch tok.Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800395 case json.Number:
Herbie Ongd2ece132020-01-07 16:45:24 -0800396 return getUint(tok, bitSize)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800397
398 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700399 // Decode number from string.
Herbie Ongd2ece132020-01-07 16:45:24 -0800400 s := strings.TrimSpace(tok.ParsedString())
401 if len(s) != len(tok.ParsedString()) {
402 return pref.Value{}, false
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700403 }
404 dec := json.NewDecoder([]byte(s))
Herbie Ongd2ece132020-01-07 16:45:24 -0800405 tok, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700406 if err != nil {
Herbie Ongd2ece132020-01-07 16:45:24 -0800407 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800408 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800409 return getUint(tok, bitSize)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800410 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800411 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800412}
413
Herbie Ongd2ece132020-01-07 16:45:24 -0800414func getUint(tok json.Token, bitSize int) (pref.Value, bool) {
415 n, ok := tok.Uint(bitSize)
416 if !ok {
417 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800418 }
419 if bitSize == 32 {
Herbie Ongd2ece132020-01-07 16:45:24 -0800420 return pref.ValueOfUint32(uint32(n)), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800421 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800422 return pref.ValueOfUint64(n), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800423}
424
Herbie Ongd2ece132020-01-07 16:45:24 -0800425func unmarshalFloat(tok json.Token, bitSize int) (pref.Value, bool) {
426 switch tok.Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800427 case json.Number:
Herbie Ongd2ece132020-01-07 16:45:24 -0800428 return getFloat(tok, bitSize)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800429
430 case json.String:
Herbie Ongd2ece132020-01-07 16:45:24 -0800431 s := tok.ParsedString()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800432 switch s {
433 case "NaN":
434 if bitSize == 32 {
Herbie Ongd2ece132020-01-07 16:45:24 -0800435 return pref.ValueOfFloat32(float32(math.NaN())), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800436 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800437 return pref.ValueOfFloat64(math.NaN()), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800438 case "Infinity":
439 if bitSize == 32 {
Herbie Ongd2ece132020-01-07 16:45:24 -0800440 return pref.ValueOfFloat32(float32(math.Inf(+1))), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800441 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800442 return pref.ValueOfFloat64(math.Inf(+1)), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800443 case "-Infinity":
444 if bitSize == 32 {
Herbie Ongd2ece132020-01-07 16:45:24 -0800445 return pref.ValueOfFloat32(float32(math.Inf(-1))), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800446 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800447 return pref.ValueOfFloat64(math.Inf(-1)), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800448 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800449
Herbie Onge52379a2019-03-15 18:00:19 -0700450 // Decode number from string.
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700451 if len(s) != len(strings.TrimSpace(s)) {
Herbie Ongd2ece132020-01-07 16:45:24 -0800452 return pref.Value{}, false
Herbie Ong06a6b0b2019-04-24 21:15:45 -0700453 }
Herbie Onge52379a2019-03-15 18:00:19 -0700454 dec := json.NewDecoder([]byte(s))
Herbie Ongd2ece132020-01-07 16:45:24 -0800455 tok, err := dec.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700456 if err != nil {
Herbie Ongd2ece132020-01-07 16:45:24 -0800457 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800458 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800459 return getFloat(tok, bitSize)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800460 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800461 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800462}
463
Herbie Ongd2ece132020-01-07 16:45:24 -0800464func getFloat(tok json.Token, bitSize int) (pref.Value, bool) {
465 n, ok := tok.Float(bitSize)
466 if !ok {
467 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800468 }
469 if bitSize == 32 {
Herbie Ongd2ece132020-01-07 16:45:24 -0800470 return pref.ValueOfFloat32(float32(n)), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800471 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800472 return pref.ValueOfFloat64(n), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800473}
474
Herbie Ongd2ece132020-01-07 16:45:24 -0800475func unmarshalBytes(tok json.Token) (pref.Value, bool) {
476 if tok.Kind() != json.String {
477 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800478 }
479
Herbie Ongd2ece132020-01-07 16:45:24 -0800480 s := tok.ParsedString()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800481 enc := base64.StdEncoding
482 if strings.ContainsAny(s, "-_") {
483 enc = base64.URLEncoding
484 }
485 if len(s)%4 != 0 {
486 enc = enc.WithPadding(base64.NoPadding)
487 }
488 b, err := enc.DecodeString(s)
489 if err != nil {
Herbie Ongd2ece132020-01-07 16:45:24 -0800490 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800491 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800492 return pref.ValueOfBytes(b), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800493}
494
Herbie Ongd2ece132020-01-07 16:45:24 -0800495func unmarshalEnum(tok json.Token, fd pref.FieldDescriptor) (pref.Value, bool) {
496 switch tok.Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800497 case json.String:
498 // Lookup EnumNumber based on name.
Herbie Ongd2ece132020-01-07 16:45:24 -0800499 s := tok.ParsedString()
Joe Tsaid24bc722019-04-15 23:39:09 -0700500 if enumVal := fd.Enum().Values().ByName(pref.Name(s)); enumVal != nil {
Herbie Ongd2ece132020-01-07 16:45:24 -0800501 return pref.ValueOfEnum(enumVal.Number()), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800502 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800503
504 case json.Number:
Herbie Ongd2ece132020-01-07 16:45:24 -0800505 if n, ok := tok.Int(32); ok {
506 return pref.ValueOfEnum(pref.EnumNumber(n)), true
Herbie Ongc96a79d2019-03-08 10:49:17 -0800507 }
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) {
Herbie Ongd2ece132020-01-07 16:45:24 -0800512 return pref.ValueOfEnum(0), true
Herbie Ong300b9fe2019-03-29 15:42:20 -0700513 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800514 }
515
Herbie Ongd2ece132020-01-07 16:45:24 -0800516 return pref.Value{}, false
Herbie Ongc96a79d2019-03-08 10:49:17 -0800517}
518
Herbie Ongd2ece132020-01-07 16:45:24 -0800519func (d decoder) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
520 tok, err := d.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700521 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800522 return err
523 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800524 if tok.Kind() != json.ArrayOpen {
525 return d.unexpectedTokenError(tok)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800526 }
527
528 switch fd.Kind() {
529 case pref.MessageKind, pref.GroupKind:
530 for {
Herbie Ongd2ece132020-01-07 16:45:24 -0800531 tok, err := d.Peek()
Damien Neil8c86fc52019-06-19 09:28:29 -0700532 if err != nil {
Herbie Ongd2ece132020-01-07 16:45:24 -0800533 return err
534 }
535
536 if tok.Kind() == json.ArrayClose {
537 d.Read()
538 return nil
539 }
540
541 val := list.NewElement()
542 if err := d.unmarshalMessage(val.Message(), false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800543 return err
544 }
Damien Neild91c4222019-09-04 10:46:00 -0700545 list.Append(val)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800546 }
547 default:
548 for {
Herbie Ongd2ece132020-01-07 16:45:24 -0800549 tok, err := d.Peek()
Damien Neil8c86fc52019-06-19 09:28:29 -0700550 if err != nil {
Herbie Ongd2ece132020-01-07 16:45:24 -0800551 return err
552 }
553
554 if tok.Kind() == json.ArrayClose {
555 d.Read()
556 return nil
557 }
558
559 val, err := d.unmarshalScalar(fd)
560 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800561 return err
562 }
563 list.Append(val)
564 }
565 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800566
Damien Neil8c86fc52019-06-19 09:28:29 -0700567 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800568}
569
Herbie Ongd2ece132020-01-07 16:45:24 -0800570func (d decoder) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
571 tok, err := d.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700572 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800573 return err
574 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800575 if tok.Kind() != json.ObjectOpen {
576 return d.unexpectedTokenError(tok)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800577 }
578
Herbie Ongc96a79d2019-03-08 10:49:17 -0800579 // Determine ahead whether map entry is a scalar type or a message type in
580 // order to call the appropriate unmarshalMapValue func inside the for loop
581 // below.
Joe Tsaiac31a352019-05-13 14:32:56 -0700582 var unmarshalMapValue func() (pref.Value, error)
583 switch fd.MapValue().Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800584 case pref.MessageKind, pref.GroupKind:
585 unmarshalMapValue = func() (pref.Value, error) {
Damien Neild91c4222019-09-04 10:46:00 -0700586 val := mmap.NewValue()
Herbie Ongd2ece132020-01-07 16:45:24 -0800587 if err := d.unmarshalMessage(val.Message(), false); err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800588 return pref.Value{}, err
589 }
Damien Neild91c4222019-09-04 10:46:00 -0700590 return val, nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800591 }
Joe Tsaiac31a352019-05-13 14:32:56 -0700592 default:
593 unmarshalMapValue = func() (pref.Value, error) {
Herbie Ongd2ece132020-01-07 16:45:24 -0800594 return d.unmarshalScalar(fd.MapValue())
Joe Tsaiac31a352019-05-13 14:32:56 -0700595 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800596 }
597
598Loop:
599 for {
600 // Read field name.
Herbie Ongd2ece132020-01-07 16:45:24 -0800601 tok, err := d.Read()
Damien Neil8c86fc52019-06-19 09:28:29 -0700602 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800603 return err
604 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800605 switch tok.Kind() {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800606 default:
Herbie Ongd2ece132020-01-07 16:45:24 -0800607 return d.unexpectedTokenError(tok)
608 case json.ObjectClose:
Herbie Ongc96a79d2019-03-08 10:49:17 -0800609 break Loop
610 case json.Name:
611 // Continue.
612 }
613
Herbie Ongc96a79d2019-03-08 10:49:17 -0800614 // Unmarshal field name.
Herbie Ongd2ece132020-01-07 16:45:24 -0800615 pkey, err := d.unmarshalMapKey(tok, fd.MapKey())
Damien Neil8c86fc52019-06-19 09:28:29 -0700616 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800617 return err
618 }
619
620 // Check for duplicate field name.
621 if mmap.Has(pkey) {
Herbie Ongd2ece132020-01-07 16:45:24 -0800622 return d.newError(tok.Pos(), "duplicate map key %v", tok.RawString())
Herbie Ongc96a79d2019-03-08 10:49:17 -0800623 }
624
625 // Read and unmarshal field value.
626 pval, err := unmarshalMapValue()
Damien Neil8c86fc52019-06-19 09:28:29 -0700627 if err != nil {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800628 return err
629 }
630
631 mmap.Set(pkey, pval)
632 }
633
Damien Neil8c86fc52019-06-19 09:28:29 -0700634 return nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800635}
636
Herbie Ongd2ece132020-01-07 16:45:24 -0800637// unmarshalMapKey converts given token of Name kind into a protoreflect.MapKey.
638// A map key type is any integral or string type.
639func (d decoder) unmarshalMapKey(tok json.Token, fd pref.FieldDescriptor) (pref.MapKey, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800640 const b32 = 32
641 const b64 = 64
642 const base10 = 10
643
Herbie Ongd2ece132020-01-07 16:45:24 -0800644 name := tok.Name()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800645 kind := fd.Kind()
646 switch kind {
647 case pref.StringKind:
Joe Tsai84177c92019-09-17 13:38:48 -0700648 return pref.ValueOfString(name).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800649
650 case pref.BoolKind:
651 switch name {
652 case "true":
Joe Tsai84177c92019-09-17 13:38:48 -0700653 return pref.ValueOfBool(true).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800654 case "false":
Joe Tsai84177c92019-09-17 13:38:48 -0700655 return pref.ValueOfBool(false).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800656 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800657
658 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800659 if n, err := strconv.ParseInt(name, base10, b32); err == nil {
660 return pref.ValueOfInt32(int32(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800661 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800662
663 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800664 if n, err := strconv.ParseInt(name, base10, b64); err == nil {
665 return pref.ValueOfInt64(int64(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800666 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800667
668 case pref.Uint32Kind, pref.Fixed32Kind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800669 if n, err := strconv.ParseUint(name, base10, b32); err == nil {
670 return pref.ValueOfUint32(uint32(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800671 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800672
673 case pref.Uint64Kind, pref.Fixed64Kind:
Herbie Ongd2ece132020-01-07 16:45:24 -0800674 if n, err := strconv.ParseUint(name, base10, b64); err == nil {
675 return pref.ValueOfUint64(uint64(n)).MapKey(), nil
Herbie Ongc96a79d2019-03-08 10:49:17 -0800676 }
Herbie Ongd2ece132020-01-07 16:45:24 -0800677
678 default:
679 panic(fmt.Sprintf("invalid kind for map key: %v", kind))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800680 }
681
Herbie Ongd2ece132020-01-07 16:45:24 -0800682 return pref.MapKey{}, d.newError(tok.Pos(), "invalid value for %v key: %s", kind, tok.RawString())
Herbie Ongc96a79d2019-03-08 10:49:17 -0800683}