1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsenpackage protojson 6*1c12ee1eSDan Willemsen 7*1c12ee1eSDan Willemsenimport ( 8*1c12ee1eSDan Willemsen "encoding/base64" 9*1c12ee1eSDan Willemsen "fmt" 10*1c12ee1eSDan Willemsen "math" 11*1c12ee1eSDan Willemsen "strconv" 12*1c12ee1eSDan Willemsen "strings" 13*1c12ee1eSDan Willemsen 14*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/encoding/json" 15*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/encoding/messageset" 16*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/errors" 17*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/flags" 18*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/genid" 19*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/pragma" 20*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/set" 21*1c12ee1eSDan Willemsen "google.golang.org/protobuf/proto" 22*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoreflect" 23*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoregistry" 24*1c12ee1eSDan Willemsen) 25*1c12ee1eSDan Willemsen 26*1c12ee1eSDan Willemsen// Unmarshal reads the given []byte into the given proto.Message. 27*1c12ee1eSDan Willemsen// The provided message must be mutable (e.g., a non-nil pointer to a message). 28*1c12ee1eSDan Willemsenfunc Unmarshal(b []byte, m proto.Message) error { 29*1c12ee1eSDan Willemsen return UnmarshalOptions{}.Unmarshal(b, m) 30*1c12ee1eSDan Willemsen} 31*1c12ee1eSDan Willemsen 32*1c12ee1eSDan Willemsen// UnmarshalOptions is a configurable JSON format parser. 33*1c12ee1eSDan Willemsentype UnmarshalOptions struct { 34*1c12ee1eSDan Willemsen pragma.NoUnkeyedLiterals 35*1c12ee1eSDan Willemsen 36*1c12ee1eSDan Willemsen // If AllowPartial is set, input for messages that will result in missing 37*1c12ee1eSDan Willemsen // required fields will not return an error. 38*1c12ee1eSDan Willemsen AllowPartial bool 39*1c12ee1eSDan Willemsen 40*1c12ee1eSDan Willemsen // If DiscardUnknown is set, unknown fields are ignored. 41*1c12ee1eSDan Willemsen DiscardUnknown bool 42*1c12ee1eSDan Willemsen 43*1c12ee1eSDan Willemsen // Resolver is used for looking up types when unmarshaling 44*1c12ee1eSDan Willemsen // google.protobuf.Any messages or extension fields. 45*1c12ee1eSDan Willemsen // If nil, this defaults to using protoregistry.GlobalTypes. 46*1c12ee1eSDan Willemsen Resolver interface { 47*1c12ee1eSDan Willemsen protoregistry.MessageTypeResolver 48*1c12ee1eSDan Willemsen protoregistry.ExtensionTypeResolver 49*1c12ee1eSDan Willemsen } 50*1c12ee1eSDan Willemsen} 51*1c12ee1eSDan Willemsen 52*1c12ee1eSDan Willemsen// Unmarshal reads the given []byte and populates the given proto.Message 53*1c12ee1eSDan Willemsen// using options in the UnmarshalOptions object. 54*1c12ee1eSDan Willemsen// It will clear the message first before setting the fields. 55*1c12ee1eSDan Willemsen// If it returns an error, the given message may be partially set. 56*1c12ee1eSDan Willemsen// The provided message must be mutable (e.g., a non-nil pointer to a message). 57*1c12ee1eSDan Willemsenfunc (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { 58*1c12ee1eSDan Willemsen return o.unmarshal(b, m) 59*1c12ee1eSDan Willemsen} 60*1c12ee1eSDan Willemsen 61*1c12ee1eSDan Willemsen// unmarshal is a centralized function that all unmarshal operations go through. 62*1c12ee1eSDan Willemsen// For profiling purposes, avoid changing the name of this function or 63*1c12ee1eSDan Willemsen// introducing other code paths for unmarshal that do not go through this. 64*1c12ee1eSDan Willemsenfunc (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error { 65*1c12ee1eSDan Willemsen proto.Reset(m) 66*1c12ee1eSDan Willemsen 67*1c12ee1eSDan Willemsen if o.Resolver == nil { 68*1c12ee1eSDan Willemsen o.Resolver = protoregistry.GlobalTypes 69*1c12ee1eSDan Willemsen } 70*1c12ee1eSDan Willemsen 71*1c12ee1eSDan Willemsen dec := decoder{json.NewDecoder(b), o} 72*1c12ee1eSDan Willemsen if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil { 73*1c12ee1eSDan Willemsen return err 74*1c12ee1eSDan Willemsen } 75*1c12ee1eSDan Willemsen 76*1c12ee1eSDan Willemsen // Check for EOF. 77*1c12ee1eSDan Willemsen tok, err := dec.Read() 78*1c12ee1eSDan Willemsen if err != nil { 79*1c12ee1eSDan Willemsen return err 80*1c12ee1eSDan Willemsen } 81*1c12ee1eSDan Willemsen if tok.Kind() != json.EOF { 82*1c12ee1eSDan Willemsen return dec.unexpectedTokenError(tok) 83*1c12ee1eSDan Willemsen } 84*1c12ee1eSDan Willemsen 85*1c12ee1eSDan Willemsen if o.AllowPartial { 86*1c12ee1eSDan Willemsen return nil 87*1c12ee1eSDan Willemsen } 88*1c12ee1eSDan Willemsen return proto.CheckInitialized(m) 89*1c12ee1eSDan Willemsen} 90*1c12ee1eSDan Willemsen 91*1c12ee1eSDan Willemsentype decoder struct { 92*1c12ee1eSDan Willemsen *json.Decoder 93*1c12ee1eSDan Willemsen opts UnmarshalOptions 94*1c12ee1eSDan Willemsen} 95*1c12ee1eSDan Willemsen 96*1c12ee1eSDan Willemsen// newError returns an error object with position info. 97*1c12ee1eSDan Willemsenfunc (d decoder) newError(pos int, f string, x ...interface{}) error { 98*1c12ee1eSDan Willemsen line, column := d.Position(pos) 99*1c12ee1eSDan Willemsen head := fmt.Sprintf("(line %d:%d): ", line, column) 100*1c12ee1eSDan Willemsen return errors.New(head+f, x...) 101*1c12ee1eSDan Willemsen} 102*1c12ee1eSDan Willemsen 103*1c12ee1eSDan Willemsen// unexpectedTokenError returns a syntax error for the given unexpected token. 104*1c12ee1eSDan Willemsenfunc (d decoder) unexpectedTokenError(tok json.Token) error { 105*1c12ee1eSDan Willemsen return d.syntaxError(tok.Pos(), "unexpected token %s", tok.RawString()) 106*1c12ee1eSDan Willemsen} 107*1c12ee1eSDan Willemsen 108*1c12ee1eSDan Willemsen// syntaxError returns a syntax error for given position. 109*1c12ee1eSDan Willemsenfunc (d decoder) syntaxError(pos int, f string, x ...interface{}) error { 110*1c12ee1eSDan Willemsen line, column := d.Position(pos) 111*1c12ee1eSDan Willemsen head := fmt.Sprintf("syntax error (line %d:%d): ", line, column) 112*1c12ee1eSDan Willemsen return errors.New(head+f, x...) 113*1c12ee1eSDan Willemsen} 114*1c12ee1eSDan Willemsen 115*1c12ee1eSDan Willemsen// unmarshalMessage unmarshals a message into the given protoreflect.Message. 116*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) error { 117*1c12ee1eSDan Willemsen if unmarshal := wellKnownTypeUnmarshaler(m.Descriptor().FullName()); unmarshal != nil { 118*1c12ee1eSDan Willemsen return unmarshal(d, m) 119*1c12ee1eSDan Willemsen } 120*1c12ee1eSDan Willemsen 121*1c12ee1eSDan Willemsen tok, err := d.Read() 122*1c12ee1eSDan Willemsen if err != nil { 123*1c12ee1eSDan Willemsen return err 124*1c12ee1eSDan Willemsen } 125*1c12ee1eSDan Willemsen if tok.Kind() != json.ObjectOpen { 126*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 127*1c12ee1eSDan Willemsen } 128*1c12ee1eSDan Willemsen 129*1c12ee1eSDan Willemsen messageDesc := m.Descriptor() 130*1c12ee1eSDan Willemsen if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { 131*1c12ee1eSDan Willemsen return errors.New("no support for proto1 MessageSets") 132*1c12ee1eSDan Willemsen } 133*1c12ee1eSDan Willemsen 134*1c12ee1eSDan Willemsen var seenNums set.Ints 135*1c12ee1eSDan Willemsen var seenOneofs set.Ints 136*1c12ee1eSDan Willemsen fieldDescs := messageDesc.Fields() 137*1c12ee1eSDan Willemsen for { 138*1c12ee1eSDan Willemsen // Read field name. 139*1c12ee1eSDan Willemsen tok, err := d.Read() 140*1c12ee1eSDan Willemsen if err != nil { 141*1c12ee1eSDan Willemsen return err 142*1c12ee1eSDan Willemsen } 143*1c12ee1eSDan Willemsen switch tok.Kind() { 144*1c12ee1eSDan Willemsen default: 145*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 146*1c12ee1eSDan Willemsen case json.ObjectClose: 147*1c12ee1eSDan Willemsen return nil 148*1c12ee1eSDan Willemsen case json.Name: 149*1c12ee1eSDan Willemsen // Continue below. 150*1c12ee1eSDan Willemsen } 151*1c12ee1eSDan Willemsen 152*1c12ee1eSDan Willemsen name := tok.Name() 153*1c12ee1eSDan Willemsen // Unmarshaling a non-custom embedded message in Any will contain the 154*1c12ee1eSDan Willemsen // JSON field "@type" which should be skipped because it is not a field 155*1c12ee1eSDan Willemsen // of the embedded message, but simply an artifact of the Any format. 156*1c12ee1eSDan Willemsen if skipTypeURL && name == "@type" { 157*1c12ee1eSDan Willemsen d.Read() 158*1c12ee1eSDan Willemsen continue 159*1c12ee1eSDan Willemsen } 160*1c12ee1eSDan Willemsen 161*1c12ee1eSDan Willemsen // Get the FieldDescriptor. 162*1c12ee1eSDan Willemsen var fd protoreflect.FieldDescriptor 163*1c12ee1eSDan Willemsen if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") { 164*1c12ee1eSDan Willemsen // Only extension names are in [name] format. 165*1c12ee1eSDan Willemsen extName := protoreflect.FullName(name[1 : len(name)-1]) 166*1c12ee1eSDan Willemsen extType, err := d.opts.Resolver.FindExtensionByName(extName) 167*1c12ee1eSDan Willemsen if err != nil && err != protoregistry.NotFound { 168*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "unable to resolve %s: %v", tok.RawString(), err) 169*1c12ee1eSDan Willemsen } 170*1c12ee1eSDan Willemsen if extType != nil { 171*1c12ee1eSDan Willemsen fd = extType.TypeDescriptor() 172*1c12ee1eSDan Willemsen if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() { 173*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName()) 174*1c12ee1eSDan Willemsen } 175*1c12ee1eSDan Willemsen } 176*1c12ee1eSDan Willemsen } else { 177*1c12ee1eSDan Willemsen // The name can either be the JSON name or the proto field name. 178*1c12ee1eSDan Willemsen fd = fieldDescs.ByJSONName(name) 179*1c12ee1eSDan Willemsen if fd == nil { 180*1c12ee1eSDan Willemsen fd = fieldDescs.ByTextName(name) 181*1c12ee1eSDan Willemsen } 182*1c12ee1eSDan Willemsen } 183*1c12ee1eSDan Willemsen if flags.ProtoLegacy { 184*1c12ee1eSDan Willemsen if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { 185*1c12ee1eSDan Willemsen fd = nil // reset since the weak reference is not linked in 186*1c12ee1eSDan Willemsen } 187*1c12ee1eSDan Willemsen } 188*1c12ee1eSDan Willemsen 189*1c12ee1eSDan Willemsen if fd == nil { 190*1c12ee1eSDan Willemsen // Field is unknown. 191*1c12ee1eSDan Willemsen if d.opts.DiscardUnknown { 192*1c12ee1eSDan Willemsen if err := d.skipJSONValue(); err != nil { 193*1c12ee1eSDan Willemsen return err 194*1c12ee1eSDan Willemsen } 195*1c12ee1eSDan Willemsen continue 196*1c12ee1eSDan Willemsen } 197*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "unknown field %v", tok.RawString()) 198*1c12ee1eSDan Willemsen } 199*1c12ee1eSDan Willemsen 200*1c12ee1eSDan Willemsen // Do not allow duplicate fields. 201*1c12ee1eSDan Willemsen num := uint64(fd.Number()) 202*1c12ee1eSDan Willemsen if seenNums.Has(num) { 203*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "duplicate field %v", tok.RawString()) 204*1c12ee1eSDan Willemsen } 205*1c12ee1eSDan Willemsen seenNums.Set(num) 206*1c12ee1eSDan Willemsen 207*1c12ee1eSDan Willemsen // No need to set values for JSON null unless the field type is 208*1c12ee1eSDan Willemsen // google.protobuf.Value or google.protobuf.NullValue. 209*1c12ee1eSDan Willemsen if tok, _ := d.Peek(); tok.Kind() == json.Null && !isKnownValue(fd) && !isNullValue(fd) { 210*1c12ee1eSDan Willemsen d.Read() 211*1c12ee1eSDan Willemsen continue 212*1c12ee1eSDan Willemsen } 213*1c12ee1eSDan Willemsen 214*1c12ee1eSDan Willemsen switch { 215*1c12ee1eSDan Willemsen case fd.IsList(): 216*1c12ee1eSDan Willemsen list := m.Mutable(fd).List() 217*1c12ee1eSDan Willemsen if err := d.unmarshalList(list, fd); err != nil { 218*1c12ee1eSDan Willemsen return err 219*1c12ee1eSDan Willemsen } 220*1c12ee1eSDan Willemsen case fd.IsMap(): 221*1c12ee1eSDan Willemsen mmap := m.Mutable(fd).Map() 222*1c12ee1eSDan Willemsen if err := d.unmarshalMap(mmap, fd); err != nil { 223*1c12ee1eSDan Willemsen return err 224*1c12ee1eSDan Willemsen } 225*1c12ee1eSDan Willemsen default: 226*1c12ee1eSDan Willemsen // If field is a oneof, check if it has already been set. 227*1c12ee1eSDan Willemsen if od := fd.ContainingOneof(); od != nil { 228*1c12ee1eSDan Willemsen idx := uint64(od.Index()) 229*1c12ee1eSDan Willemsen if seenOneofs.Has(idx) { 230*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "error parsing %s, oneof %v is already set", tok.RawString(), od.FullName()) 231*1c12ee1eSDan Willemsen } 232*1c12ee1eSDan Willemsen seenOneofs.Set(idx) 233*1c12ee1eSDan Willemsen } 234*1c12ee1eSDan Willemsen 235*1c12ee1eSDan Willemsen // Required or optional fields. 236*1c12ee1eSDan Willemsen if err := d.unmarshalSingular(m, fd); err != nil { 237*1c12ee1eSDan Willemsen return err 238*1c12ee1eSDan Willemsen } 239*1c12ee1eSDan Willemsen } 240*1c12ee1eSDan Willemsen } 241*1c12ee1eSDan Willemsen} 242*1c12ee1eSDan Willemsen 243*1c12ee1eSDan Willemsenfunc isKnownValue(fd protoreflect.FieldDescriptor) bool { 244*1c12ee1eSDan Willemsen md := fd.Message() 245*1c12ee1eSDan Willemsen return md != nil && md.FullName() == genid.Value_message_fullname 246*1c12ee1eSDan Willemsen} 247*1c12ee1eSDan Willemsen 248*1c12ee1eSDan Willemsenfunc isNullValue(fd protoreflect.FieldDescriptor) bool { 249*1c12ee1eSDan Willemsen ed := fd.Enum() 250*1c12ee1eSDan Willemsen return ed != nil && ed.FullName() == genid.NullValue_enum_fullname 251*1c12ee1eSDan Willemsen} 252*1c12ee1eSDan Willemsen 253*1c12ee1eSDan Willemsen// unmarshalSingular unmarshals to the non-repeated field specified 254*1c12ee1eSDan Willemsen// by the given FieldDescriptor. 255*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalSingular(m protoreflect.Message, fd protoreflect.FieldDescriptor) error { 256*1c12ee1eSDan Willemsen var val protoreflect.Value 257*1c12ee1eSDan Willemsen var err error 258*1c12ee1eSDan Willemsen switch fd.Kind() { 259*1c12ee1eSDan Willemsen case protoreflect.MessageKind, protoreflect.GroupKind: 260*1c12ee1eSDan Willemsen val = m.NewField(fd) 261*1c12ee1eSDan Willemsen err = d.unmarshalMessage(val.Message(), false) 262*1c12ee1eSDan Willemsen default: 263*1c12ee1eSDan Willemsen val, err = d.unmarshalScalar(fd) 264*1c12ee1eSDan Willemsen } 265*1c12ee1eSDan Willemsen 266*1c12ee1eSDan Willemsen if err != nil { 267*1c12ee1eSDan Willemsen return err 268*1c12ee1eSDan Willemsen } 269*1c12ee1eSDan Willemsen m.Set(fd, val) 270*1c12ee1eSDan Willemsen return nil 271*1c12ee1eSDan Willemsen} 272*1c12ee1eSDan Willemsen 273*1c12ee1eSDan Willemsen// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by 274*1c12ee1eSDan Willemsen// the given FieldDescriptor. 275*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { 276*1c12ee1eSDan Willemsen const b32 int = 32 277*1c12ee1eSDan Willemsen const b64 int = 64 278*1c12ee1eSDan Willemsen 279*1c12ee1eSDan Willemsen tok, err := d.Read() 280*1c12ee1eSDan Willemsen if err != nil { 281*1c12ee1eSDan Willemsen return protoreflect.Value{}, err 282*1c12ee1eSDan Willemsen } 283*1c12ee1eSDan Willemsen 284*1c12ee1eSDan Willemsen kind := fd.Kind() 285*1c12ee1eSDan Willemsen switch kind { 286*1c12ee1eSDan Willemsen case protoreflect.BoolKind: 287*1c12ee1eSDan Willemsen if tok.Kind() == json.Bool { 288*1c12ee1eSDan Willemsen return protoreflect.ValueOfBool(tok.Bool()), nil 289*1c12ee1eSDan Willemsen } 290*1c12ee1eSDan Willemsen 291*1c12ee1eSDan Willemsen case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: 292*1c12ee1eSDan Willemsen if v, ok := unmarshalInt(tok, b32); ok { 293*1c12ee1eSDan Willemsen return v, nil 294*1c12ee1eSDan Willemsen } 295*1c12ee1eSDan Willemsen 296*1c12ee1eSDan Willemsen case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 297*1c12ee1eSDan Willemsen if v, ok := unmarshalInt(tok, b64); ok { 298*1c12ee1eSDan Willemsen return v, nil 299*1c12ee1eSDan Willemsen } 300*1c12ee1eSDan Willemsen 301*1c12ee1eSDan Willemsen case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: 302*1c12ee1eSDan Willemsen if v, ok := unmarshalUint(tok, b32); ok { 303*1c12ee1eSDan Willemsen return v, nil 304*1c12ee1eSDan Willemsen } 305*1c12ee1eSDan Willemsen 306*1c12ee1eSDan Willemsen case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 307*1c12ee1eSDan Willemsen if v, ok := unmarshalUint(tok, b64); ok { 308*1c12ee1eSDan Willemsen return v, nil 309*1c12ee1eSDan Willemsen } 310*1c12ee1eSDan Willemsen 311*1c12ee1eSDan Willemsen case protoreflect.FloatKind: 312*1c12ee1eSDan Willemsen if v, ok := unmarshalFloat(tok, b32); ok { 313*1c12ee1eSDan Willemsen return v, nil 314*1c12ee1eSDan Willemsen } 315*1c12ee1eSDan Willemsen 316*1c12ee1eSDan Willemsen case protoreflect.DoubleKind: 317*1c12ee1eSDan Willemsen if v, ok := unmarshalFloat(tok, b64); ok { 318*1c12ee1eSDan Willemsen return v, nil 319*1c12ee1eSDan Willemsen } 320*1c12ee1eSDan Willemsen 321*1c12ee1eSDan Willemsen case protoreflect.StringKind: 322*1c12ee1eSDan Willemsen if tok.Kind() == json.String { 323*1c12ee1eSDan Willemsen return protoreflect.ValueOfString(tok.ParsedString()), nil 324*1c12ee1eSDan Willemsen } 325*1c12ee1eSDan Willemsen 326*1c12ee1eSDan Willemsen case protoreflect.BytesKind: 327*1c12ee1eSDan Willemsen if v, ok := unmarshalBytes(tok); ok { 328*1c12ee1eSDan Willemsen return v, nil 329*1c12ee1eSDan Willemsen } 330*1c12ee1eSDan Willemsen 331*1c12ee1eSDan Willemsen case protoreflect.EnumKind: 332*1c12ee1eSDan Willemsen if v, ok := unmarshalEnum(tok, fd); ok { 333*1c12ee1eSDan Willemsen return v, nil 334*1c12ee1eSDan Willemsen } 335*1c12ee1eSDan Willemsen 336*1c12ee1eSDan Willemsen default: 337*1c12ee1eSDan Willemsen panic(fmt.Sprintf("unmarshalScalar: invalid scalar kind %v", kind)) 338*1c12ee1eSDan Willemsen } 339*1c12ee1eSDan Willemsen 340*1c12ee1eSDan Willemsen return protoreflect.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString()) 341*1c12ee1eSDan Willemsen} 342*1c12ee1eSDan Willemsen 343*1c12ee1eSDan Willemsenfunc unmarshalInt(tok json.Token, bitSize int) (protoreflect.Value, bool) { 344*1c12ee1eSDan Willemsen switch tok.Kind() { 345*1c12ee1eSDan Willemsen case json.Number: 346*1c12ee1eSDan Willemsen return getInt(tok, bitSize) 347*1c12ee1eSDan Willemsen 348*1c12ee1eSDan Willemsen case json.String: 349*1c12ee1eSDan Willemsen // Decode number from string. 350*1c12ee1eSDan Willemsen s := strings.TrimSpace(tok.ParsedString()) 351*1c12ee1eSDan Willemsen if len(s) != len(tok.ParsedString()) { 352*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 353*1c12ee1eSDan Willemsen } 354*1c12ee1eSDan Willemsen dec := json.NewDecoder([]byte(s)) 355*1c12ee1eSDan Willemsen tok, err := dec.Read() 356*1c12ee1eSDan Willemsen if err != nil { 357*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 358*1c12ee1eSDan Willemsen } 359*1c12ee1eSDan Willemsen return getInt(tok, bitSize) 360*1c12ee1eSDan Willemsen } 361*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 362*1c12ee1eSDan Willemsen} 363*1c12ee1eSDan Willemsen 364*1c12ee1eSDan Willemsenfunc getInt(tok json.Token, bitSize int) (protoreflect.Value, bool) { 365*1c12ee1eSDan Willemsen n, ok := tok.Int(bitSize) 366*1c12ee1eSDan Willemsen if !ok { 367*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 368*1c12ee1eSDan Willemsen } 369*1c12ee1eSDan Willemsen if bitSize == 32 { 370*1c12ee1eSDan Willemsen return protoreflect.ValueOfInt32(int32(n)), true 371*1c12ee1eSDan Willemsen } 372*1c12ee1eSDan Willemsen return protoreflect.ValueOfInt64(n), true 373*1c12ee1eSDan Willemsen} 374*1c12ee1eSDan Willemsen 375*1c12ee1eSDan Willemsenfunc unmarshalUint(tok json.Token, bitSize int) (protoreflect.Value, bool) { 376*1c12ee1eSDan Willemsen switch tok.Kind() { 377*1c12ee1eSDan Willemsen case json.Number: 378*1c12ee1eSDan Willemsen return getUint(tok, bitSize) 379*1c12ee1eSDan Willemsen 380*1c12ee1eSDan Willemsen case json.String: 381*1c12ee1eSDan Willemsen // Decode number from string. 382*1c12ee1eSDan Willemsen s := strings.TrimSpace(tok.ParsedString()) 383*1c12ee1eSDan Willemsen if len(s) != len(tok.ParsedString()) { 384*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 385*1c12ee1eSDan Willemsen } 386*1c12ee1eSDan Willemsen dec := json.NewDecoder([]byte(s)) 387*1c12ee1eSDan Willemsen tok, err := dec.Read() 388*1c12ee1eSDan Willemsen if err != nil { 389*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 390*1c12ee1eSDan Willemsen } 391*1c12ee1eSDan Willemsen return getUint(tok, bitSize) 392*1c12ee1eSDan Willemsen } 393*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 394*1c12ee1eSDan Willemsen} 395*1c12ee1eSDan Willemsen 396*1c12ee1eSDan Willemsenfunc getUint(tok json.Token, bitSize int) (protoreflect.Value, bool) { 397*1c12ee1eSDan Willemsen n, ok := tok.Uint(bitSize) 398*1c12ee1eSDan Willemsen if !ok { 399*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 400*1c12ee1eSDan Willemsen } 401*1c12ee1eSDan Willemsen if bitSize == 32 { 402*1c12ee1eSDan Willemsen return protoreflect.ValueOfUint32(uint32(n)), true 403*1c12ee1eSDan Willemsen } 404*1c12ee1eSDan Willemsen return protoreflect.ValueOfUint64(n), true 405*1c12ee1eSDan Willemsen} 406*1c12ee1eSDan Willemsen 407*1c12ee1eSDan Willemsenfunc unmarshalFloat(tok json.Token, bitSize int) (protoreflect.Value, bool) { 408*1c12ee1eSDan Willemsen switch tok.Kind() { 409*1c12ee1eSDan Willemsen case json.Number: 410*1c12ee1eSDan Willemsen return getFloat(tok, bitSize) 411*1c12ee1eSDan Willemsen 412*1c12ee1eSDan Willemsen case json.String: 413*1c12ee1eSDan Willemsen s := tok.ParsedString() 414*1c12ee1eSDan Willemsen switch s { 415*1c12ee1eSDan Willemsen case "NaN": 416*1c12ee1eSDan Willemsen if bitSize == 32 { 417*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat32(float32(math.NaN())), true 418*1c12ee1eSDan Willemsen } 419*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat64(math.NaN()), true 420*1c12ee1eSDan Willemsen case "Infinity": 421*1c12ee1eSDan Willemsen if bitSize == 32 { 422*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat32(float32(math.Inf(+1))), true 423*1c12ee1eSDan Willemsen } 424*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat64(math.Inf(+1)), true 425*1c12ee1eSDan Willemsen case "-Infinity": 426*1c12ee1eSDan Willemsen if bitSize == 32 { 427*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat32(float32(math.Inf(-1))), true 428*1c12ee1eSDan Willemsen } 429*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat64(math.Inf(-1)), true 430*1c12ee1eSDan Willemsen } 431*1c12ee1eSDan Willemsen 432*1c12ee1eSDan Willemsen // Decode number from string. 433*1c12ee1eSDan Willemsen if len(s) != len(strings.TrimSpace(s)) { 434*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 435*1c12ee1eSDan Willemsen } 436*1c12ee1eSDan Willemsen dec := json.NewDecoder([]byte(s)) 437*1c12ee1eSDan Willemsen tok, err := dec.Read() 438*1c12ee1eSDan Willemsen if err != nil { 439*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 440*1c12ee1eSDan Willemsen } 441*1c12ee1eSDan Willemsen return getFloat(tok, bitSize) 442*1c12ee1eSDan Willemsen } 443*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 444*1c12ee1eSDan Willemsen} 445*1c12ee1eSDan Willemsen 446*1c12ee1eSDan Willemsenfunc getFloat(tok json.Token, bitSize int) (protoreflect.Value, bool) { 447*1c12ee1eSDan Willemsen n, ok := tok.Float(bitSize) 448*1c12ee1eSDan Willemsen if !ok { 449*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 450*1c12ee1eSDan Willemsen } 451*1c12ee1eSDan Willemsen if bitSize == 32 { 452*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat32(float32(n)), true 453*1c12ee1eSDan Willemsen } 454*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat64(n), true 455*1c12ee1eSDan Willemsen} 456*1c12ee1eSDan Willemsen 457*1c12ee1eSDan Willemsenfunc unmarshalBytes(tok json.Token) (protoreflect.Value, bool) { 458*1c12ee1eSDan Willemsen if tok.Kind() != json.String { 459*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 460*1c12ee1eSDan Willemsen } 461*1c12ee1eSDan Willemsen 462*1c12ee1eSDan Willemsen s := tok.ParsedString() 463*1c12ee1eSDan Willemsen enc := base64.StdEncoding 464*1c12ee1eSDan Willemsen if strings.ContainsAny(s, "-_") { 465*1c12ee1eSDan Willemsen enc = base64.URLEncoding 466*1c12ee1eSDan Willemsen } 467*1c12ee1eSDan Willemsen if len(s)%4 != 0 { 468*1c12ee1eSDan Willemsen enc = enc.WithPadding(base64.NoPadding) 469*1c12ee1eSDan Willemsen } 470*1c12ee1eSDan Willemsen b, err := enc.DecodeString(s) 471*1c12ee1eSDan Willemsen if err != nil { 472*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 473*1c12ee1eSDan Willemsen } 474*1c12ee1eSDan Willemsen return protoreflect.ValueOfBytes(b), true 475*1c12ee1eSDan Willemsen} 476*1c12ee1eSDan Willemsen 477*1c12ee1eSDan Willemsenfunc unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflect.Value, bool) { 478*1c12ee1eSDan Willemsen switch tok.Kind() { 479*1c12ee1eSDan Willemsen case json.String: 480*1c12ee1eSDan Willemsen // Lookup EnumNumber based on name. 481*1c12ee1eSDan Willemsen s := tok.ParsedString() 482*1c12ee1eSDan Willemsen if enumVal := fd.Enum().Values().ByName(protoreflect.Name(s)); enumVal != nil { 483*1c12ee1eSDan Willemsen return protoreflect.ValueOfEnum(enumVal.Number()), true 484*1c12ee1eSDan Willemsen } 485*1c12ee1eSDan Willemsen 486*1c12ee1eSDan Willemsen case json.Number: 487*1c12ee1eSDan Willemsen if n, ok := tok.Int(32); ok { 488*1c12ee1eSDan Willemsen return protoreflect.ValueOfEnum(protoreflect.EnumNumber(n)), true 489*1c12ee1eSDan Willemsen } 490*1c12ee1eSDan Willemsen 491*1c12ee1eSDan Willemsen case json.Null: 492*1c12ee1eSDan Willemsen // This is only valid for google.protobuf.NullValue. 493*1c12ee1eSDan Willemsen if isNullValue(fd) { 494*1c12ee1eSDan Willemsen return protoreflect.ValueOfEnum(0), true 495*1c12ee1eSDan Willemsen } 496*1c12ee1eSDan Willemsen } 497*1c12ee1eSDan Willemsen 498*1c12ee1eSDan Willemsen return protoreflect.Value{}, false 499*1c12ee1eSDan Willemsen} 500*1c12ee1eSDan Willemsen 501*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalList(list protoreflect.List, fd protoreflect.FieldDescriptor) error { 502*1c12ee1eSDan Willemsen tok, err := d.Read() 503*1c12ee1eSDan Willemsen if err != nil { 504*1c12ee1eSDan Willemsen return err 505*1c12ee1eSDan Willemsen } 506*1c12ee1eSDan Willemsen if tok.Kind() != json.ArrayOpen { 507*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 508*1c12ee1eSDan Willemsen } 509*1c12ee1eSDan Willemsen 510*1c12ee1eSDan Willemsen switch fd.Kind() { 511*1c12ee1eSDan Willemsen case protoreflect.MessageKind, protoreflect.GroupKind: 512*1c12ee1eSDan Willemsen for { 513*1c12ee1eSDan Willemsen tok, err := d.Peek() 514*1c12ee1eSDan Willemsen if err != nil { 515*1c12ee1eSDan Willemsen return err 516*1c12ee1eSDan Willemsen } 517*1c12ee1eSDan Willemsen 518*1c12ee1eSDan Willemsen if tok.Kind() == json.ArrayClose { 519*1c12ee1eSDan Willemsen d.Read() 520*1c12ee1eSDan Willemsen return nil 521*1c12ee1eSDan Willemsen } 522*1c12ee1eSDan Willemsen 523*1c12ee1eSDan Willemsen val := list.NewElement() 524*1c12ee1eSDan Willemsen if err := d.unmarshalMessage(val.Message(), false); err != nil { 525*1c12ee1eSDan Willemsen return err 526*1c12ee1eSDan Willemsen } 527*1c12ee1eSDan Willemsen list.Append(val) 528*1c12ee1eSDan Willemsen } 529*1c12ee1eSDan Willemsen default: 530*1c12ee1eSDan Willemsen for { 531*1c12ee1eSDan Willemsen tok, err := d.Peek() 532*1c12ee1eSDan Willemsen if err != nil { 533*1c12ee1eSDan Willemsen return err 534*1c12ee1eSDan Willemsen } 535*1c12ee1eSDan Willemsen 536*1c12ee1eSDan Willemsen if tok.Kind() == json.ArrayClose { 537*1c12ee1eSDan Willemsen d.Read() 538*1c12ee1eSDan Willemsen return nil 539*1c12ee1eSDan Willemsen } 540*1c12ee1eSDan Willemsen 541*1c12ee1eSDan Willemsen val, err := d.unmarshalScalar(fd) 542*1c12ee1eSDan Willemsen if err != nil { 543*1c12ee1eSDan Willemsen return err 544*1c12ee1eSDan Willemsen } 545*1c12ee1eSDan Willemsen list.Append(val) 546*1c12ee1eSDan Willemsen } 547*1c12ee1eSDan Willemsen } 548*1c12ee1eSDan Willemsen 549*1c12ee1eSDan Willemsen return nil 550*1c12ee1eSDan Willemsen} 551*1c12ee1eSDan Willemsen 552*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMap(mmap protoreflect.Map, fd protoreflect.FieldDescriptor) error { 553*1c12ee1eSDan Willemsen tok, err := d.Read() 554*1c12ee1eSDan Willemsen if err != nil { 555*1c12ee1eSDan Willemsen return err 556*1c12ee1eSDan Willemsen } 557*1c12ee1eSDan Willemsen if tok.Kind() != json.ObjectOpen { 558*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 559*1c12ee1eSDan Willemsen } 560*1c12ee1eSDan Willemsen 561*1c12ee1eSDan Willemsen // Determine ahead whether map entry is a scalar type or a message type in 562*1c12ee1eSDan Willemsen // order to call the appropriate unmarshalMapValue func inside the for loop 563*1c12ee1eSDan Willemsen // below. 564*1c12ee1eSDan Willemsen var unmarshalMapValue func() (protoreflect.Value, error) 565*1c12ee1eSDan Willemsen switch fd.MapValue().Kind() { 566*1c12ee1eSDan Willemsen case protoreflect.MessageKind, protoreflect.GroupKind: 567*1c12ee1eSDan Willemsen unmarshalMapValue = func() (protoreflect.Value, error) { 568*1c12ee1eSDan Willemsen val := mmap.NewValue() 569*1c12ee1eSDan Willemsen if err := d.unmarshalMessage(val.Message(), false); err != nil { 570*1c12ee1eSDan Willemsen return protoreflect.Value{}, err 571*1c12ee1eSDan Willemsen } 572*1c12ee1eSDan Willemsen return val, nil 573*1c12ee1eSDan Willemsen } 574*1c12ee1eSDan Willemsen default: 575*1c12ee1eSDan Willemsen unmarshalMapValue = func() (protoreflect.Value, error) { 576*1c12ee1eSDan Willemsen return d.unmarshalScalar(fd.MapValue()) 577*1c12ee1eSDan Willemsen } 578*1c12ee1eSDan Willemsen } 579*1c12ee1eSDan Willemsen 580*1c12ee1eSDan WillemsenLoop: 581*1c12ee1eSDan Willemsen for { 582*1c12ee1eSDan Willemsen // Read field name. 583*1c12ee1eSDan Willemsen tok, err := d.Read() 584*1c12ee1eSDan Willemsen if err != nil { 585*1c12ee1eSDan Willemsen return err 586*1c12ee1eSDan Willemsen } 587*1c12ee1eSDan Willemsen switch tok.Kind() { 588*1c12ee1eSDan Willemsen default: 589*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 590*1c12ee1eSDan Willemsen case json.ObjectClose: 591*1c12ee1eSDan Willemsen break Loop 592*1c12ee1eSDan Willemsen case json.Name: 593*1c12ee1eSDan Willemsen // Continue. 594*1c12ee1eSDan Willemsen } 595*1c12ee1eSDan Willemsen 596*1c12ee1eSDan Willemsen // Unmarshal field name. 597*1c12ee1eSDan Willemsen pkey, err := d.unmarshalMapKey(tok, fd.MapKey()) 598*1c12ee1eSDan Willemsen if err != nil { 599*1c12ee1eSDan Willemsen return err 600*1c12ee1eSDan Willemsen } 601*1c12ee1eSDan Willemsen 602*1c12ee1eSDan Willemsen // Check for duplicate field name. 603*1c12ee1eSDan Willemsen if mmap.Has(pkey) { 604*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "duplicate map key %v", tok.RawString()) 605*1c12ee1eSDan Willemsen } 606*1c12ee1eSDan Willemsen 607*1c12ee1eSDan Willemsen // Read and unmarshal field value. 608*1c12ee1eSDan Willemsen pval, err := unmarshalMapValue() 609*1c12ee1eSDan Willemsen if err != nil { 610*1c12ee1eSDan Willemsen return err 611*1c12ee1eSDan Willemsen } 612*1c12ee1eSDan Willemsen 613*1c12ee1eSDan Willemsen mmap.Set(pkey, pval) 614*1c12ee1eSDan Willemsen } 615*1c12ee1eSDan Willemsen 616*1c12ee1eSDan Willemsen return nil 617*1c12ee1eSDan Willemsen} 618*1c12ee1eSDan Willemsen 619*1c12ee1eSDan Willemsen// unmarshalMapKey converts given token of Name kind into a protoreflect.MapKey. 620*1c12ee1eSDan Willemsen// A map key type is any integral or string type. 621*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMapKey(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflect.MapKey, error) { 622*1c12ee1eSDan Willemsen const b32 = 32 623*1c12ee1eSDan Willemsen const b64 = 64 624*1c12ee1eSDan Willemsen const base10 = 10 625*1c12ee1eSDan Willemsen 626*1c12ee1eSDan Willemsen name := tok.Name() 627*1c12ee1eSDan Willemsen kind := fd.Kind() 628*1c12ee1eSDan Willemsen switch kind { 629*1c12ee1eSDan Willemsen case protoreflect.StringKind: 630*1c12ee1eSDan Willemsen return protoreflect.ValueOfString(name).MapKey(), nil 631*1c12ee1eSDan Willemsen 632*1c12ee1eSDan Willemsen case protoreflect.BoolKind: 633*1c12ee1eSDan Willemsen switch name { 634*1c12ee1eSDan Willemsen case "true": 635*1c12ee1eSDan Willemsen return protoreflect.ValueOfBool(true).MapKey(), nil 636*1c12ee1eSDan Willemsen case "false": 637*1c12ee1eSDan Willemsen return protoreflect.ValueOfBool(false).MapKey(), nil 638*1c12ee1eSDan Willemsen } 639*1c12ee1eSDan Willemsen 640*1c12ee1eSDan Willemsen case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: 641*1c12ee1eSDan Willemsen if n, err := strconv.ParseInt(name, base10, b32); err == nil { 642*1c12ee1eSDan Willemsen return protoreflect.ValueOfInt32(int32(n)).MapKey(), nil 643*1c12ee1eSDan Willemsen } 644*1c12ee1eSDan Willemsen 645*1c12ee1eSDan Willemsen case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 646*1c12ee1eSDan Willemsen if n, err := strconv.ParseInt(name, base10, b64); err == nil { 647*1c12ee1eSDan Willemsen return protoreflect.ValueOfInt64(int64(n)).MapKey(), nil 648*1c12ee1eSDan Willemsen } 649*1c12ee1eSDan Willemsen 650*1c12ee1eSDan Willemsen case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: 651*1c12ee1eSDan Willemsen if n, err := strconv.ParseUint(name, base10, b32); err == nil { 652*1c12ee1eSDan Willemsen return protoreflect.ValueOfUint32(uint32(n)).MapKey(), nil 653*1c12ee1eSDan Willemsen } 654*1c12ee1eSDan Willemsen 655*1c12ee1eSDan Willemsen case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 656*1c12ee1eSDan Willemsen if n, err := strconv.ParseUint(name, base10, b64); err == nil { 657*1c12ee1eSDan Willemsen return protoreflect.ValueOfUint64(uint64(n)).MapKey(), nil 658*1c12ee1eSDan Willemsen } 659*1c12ee1eSDan Willemsen 660*1c12ee1eSDan Willemsen default: 661*1c12ee1eSDan Willemsen panic(fmt.Sprintf("invalid kind for map key: %v", kind)) 662*1c12ee1eSDan Willemsen } 663*1c12ee1eSDan Willemsen 664*1c12ee1eSDan Willemsen return protoreflect.MapKey{}, d.newError(tok.Pos(), "invalid value for %v key: %s", kind, tok.RawString()) 665*1c12ee1eSDan Willemsen} 666