1*1c12ee1eSDan Willemsen// Copyright 2018 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 prototext 6*1c12ee1eSDan Willemsen 7*1c12ee1eSDan Willemsenimport ( 8*1c12ee1eSDan Willemsen "fmt" 9*1c12ee1eSDan Willemsen "unicode/utf8" 10*1c12ee1eSDan Willemsen 11*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/encoding/messageset" 12*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/encoding/text" 13*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/errors" 14*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/flags" 15*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/genid" 16*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/pragma" 17*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/set" 18*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/strs" 19*1c12ee1eSDan Willemsen "google.golang.org/protobuf/proto" 20*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoreflect" 21*1c12ee1eSDan Willemsen "google.golang.org/protobuf/reflect/protoregistry" 22*1c12ee1eSDan Willemsen) 23*1c12ee1eSDan Willemsen 24*1c12ee1eSDan Willemsen// Unmarshal reads the given []byte into the given proto.Message. 25*1c12ee1eSDan Willemsen// The provided message must be mutable (e.g., a non-nil pointer to a message). 26*1c12ee1eSDan Willemsenfunc Unmarshal(b []byte, m proto.Message) error { 27*1c12ee1eSDan Willemsen return UnmarshalOptions{}.Unmarshal(b, m) 28*1c12ee1eSDan Willemsen} 29*1c12ee1eSDan Willemsen 30*1c12ee1eSDan Willemsen// UnmarshalOptions is a configurable textproto format unmarshaler. 31*1c12ee1eSDan Willemsentype UnmarshalOptions struct { 32*1c12ee1eSDan Willemsen pragma.NoUnkeyedLiterals 33*1c12ee1eSDan Willemsen 34*1c12ee1eSDan Willemsen // AllowPartial accepts input for messages that will result in missing 35*1c12ee1eSDan Willemsen // required fields. If AllowPartial is false (the default), Unmarshal will 36*1c12ee1eSDan Willemsen // return error if there are any missing required fields. 37*1c12ee1eSDan Willemsen AllowPartial bool 38*1c12ee1eSDan Willemsen 39*1c12ee1eSDan Willemsen // DiscardUnknown specifies whether to ignore unknown fields when parsing. 40*1c12ee1eSDan Willemsen // An unknown field is any field whose field name or field number does not 41*1c12ee1eSDan Willemsen // resolve to any known or extension field in the message. 42*1c12ee1eSDan Willemsen // By default, unmarshal rejects unknown fields as an error. 43*1c12ee1eSDan Willemsen DiscardUnknown bool 44*1c12ee1eSDan Willemsen 45*1c12ee1eSDan Willemsen // Resolver is used for looking up types when unmarshaling 46*1c12ee1eSDan Willemsen // google.protobuf.Any messages or extension fields. 47*1c12ee1eSDan Willemsen // If nil, this defaults to using protoregistry.GlobalTypes. 48*1c12ee1eSDan Willemsen Resolver interface { 49*1c12ee1eSDan Willemsen protoregistry.MessageTypeResolver 50*1c12ee1eSDan Willemsen protoregistry.ExtensionTypeResolver 51*1c12ee1eSDan Willemsen } 52*1c12ee1eSDan Willemsen} 53*1c12ee1eSDan Willemsen 54*1c12ee1eSDan Willemsen// Unmarshal reads the given []byte and populates the given proto.Message 55*1c12ee1eSDan Willemsen// using options in the UnmarshalOptions object. 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{text.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 if o.AllowPartial { 76*1c12ee1eSDan Willemsen return nil 77*1c12ee1eSDan Willemsen } 78*1c12ee1eSDan Willemsen return proto.CheckInitialized(m) 79*1c12ee1eSDan Willemsen} 80*1c12ee1eSDan Willemsen 81*1c12ee1eSDan Willemsentype decoder struct { 82*1c12ee1eSDan Willemsen *text.Decoder 83*1c12ee1eSDan Willemsen opts UnmarshalOptions 84*1c12ee1eSDan Willemsen} 85*1c12ee1eSDan Willemsen 86*1c12ee1eSDan Willemsen// newError returns an error object with position info. 87*1c12ee1eSDan Willemsenfunc (d decoder) newError(pos int, f string, x ...interface{}) error { 88*1c12ee1eSDan Willemsen line, column := d.Position(pos) 89*1c12ee1eSDan Willemsen head := fmt.Sprintf("(line %d:%d): ", line, column) 90*1c12ee1eSDan Willemsen return errors.New(head+f, x...) 91*1c12ee1eSDan Willemsen} 92*1c12ee1eSDan Willemsen 93*1c12ee1eSDan Willemsen// unexpectedTokenError returns a syntax error for the given unexpected token. 94*1c12ee1eSDan Willemsenfunc (d decoder) unexpectedTokenError(tok text.Token) error { 95*1c12ee1eSDan Willemsen return d.syntaxError(tok.Pos(), "unexpected token: %s", tok.RawString()) 96*1c12ee1eSDan Willemsen} 97*1c12ee1eSDan Willemsen 98*1c12ee1eSDan Willemsen// syntaxError returns a syntax error for given position. 99*1c12ee1eSDan Willemsenfunc (d decoder) syntaxError(pos int, f string, x ...interface{}) error { 100*1c12ee1eSDan Willemsen line, column := d.Position(pos) 101*1c12ee1eSDan Willemsen head := fmt.Sprintf("syntax error (line %d:%d): ", line, column) 102*1c12ee1eSDan Willemsen return errors.New(head+f, x...) 103*1c12ee1eSDan Willemsen} 104*1c12ee1eSDan Willemsen 105*1c12ee1eSDan Willemsen// unmarshalMessage unmarshals into the given protoreflect.Message. 106*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMessage(m protoreflect.Message, checkDelims bool) error { 107*1c12ee1eSDan Willemsen messageDesc := m.Descriptor() 108*1c12ee1eSDan Willemsen if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { 109*1c12ee1eSDan Willemsen return errors.New("no support for proto1 MessageSets") 110*1c12ee1eSDan Willemsen } 111*1c12ee1eSDan Willemsen 112*1c12ee1eSDan Willemsen if messageDesc.FullName() == genid.Any_message_fullname { 113*1c12ee1eSDan Willemsen return d.unmarshalAny(m, checkDelims) 114*1c12ee1eSDan Willemsen } 115*1c12ee1eSDan Willemsen 116*1c12ee1eSDan Willemsen if checkDelims { 117*1c12ee1eSDan Willemsen tok, err := d.Read() 118*1c12ee1eSDan Willemsen if err != nil { 119*1c12ee1eSDan Willemsen return err 120*1c12ee1eSDan Willemsen } 121*1c12ee1eSDan Willemsen 122*1c12ee1eSDan Willemsen if tok.Kind() != text.MessageOpen { 123*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 124*1c12ee1eSDan Willemsen } 125*1c12ee1eSDan Willemsen } 126*1c12ee1eSDan Willemsen 127*1c12ee1eSDan Willemsen var seenNums set.Ints 128*1c12ee1eSDan Willemsen var seenOneofs set.Ints 129*1c12ee1eSDan Willemsen fieldDescs := messageDesc.Fields() 130*1c12ee1eSDan Willemsen 131*1c12ee1eSDan Willemsen for { 132*1c12ee1eSDan Willemsen // Read field name. 133*1c12ee1eSDan Willemsen tok, err := d.Read() 134*1c12ee1eSDan Willemsen if err != nil { 135*1c12ee1eSDan Willemsen return err 136*1c12ee1eSDan Willemsen } 137*1c12ee1eSDan Willemsen switch typ := tok.Kind(); typ { 138*1c12ee1eSDan Willemsen case text.Name: 139*1c12ee1eSDan Willemsen // Continue below. 140*1c12ee1eSDan Willemsen case text.EOF: 141*1c12ee1eSDan Willemsen if checkDelims { 142*1c12ee1eSDan Willemsen return text.ErrUnexpectedEOF 143*1c12ee1eSDan Willemsen } 144*1c12ee1eSDan Willemsen return nil 145*1c12ee1eSDan Willemsen default: 146*1c12ee1eSDan Willemsen if checkDelims && typ == text.MessageClose { 147*1c12ee1eSDan Willemsen return nil 148*1c12ee1eSDan Willemsen } 149*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 150*1c12ee1eSDan Willemsen } 151*1c12ee1eSDan Willemsen 152*1c12ee1eSDan Willemsen // Resolve the field descriptor. 153*1c12ee1eSDan Willemsen var name protoreflect.Name 154*1c12ee1eSDan Willemsen var fd protoreflect.FieldDescriptor 155*1c12ee1eSDan Willemsen var xt protoreflect.ExtensionType 156*1c12ee1eSDan Willemsen var xtErr error 157*1c12ee1eSDan Willemsen var isFieldNumberName bool 158*1c12ee1eSDan Willemsen 159*1c12ee1eSDan Willemsen switch tok.NameKind() { 160*1c12ee1eSDan Willemsen case text.IdentName: 161*1c12ee1eSDan Willemsen name = protoreflect.Name(tok.IdentName()) 162*1c12ee1eSDan Willemsen fd = fieldDescs.ByTextName(string(name)) 163*1c12ee1eSDan Willemsen 164*1c12ee1eSDan Willemsen case text.TypeName: 165*1c12ee1eSDan Willemsen // Handle extensions only. This code path is not for Any. 166*1c12ee1eSDan Willemsen xt, xtErr = d.opts.Resolver.FindExtensionByName(protoreflect.FullName(tok.TypeName())) 167*1c12ee1eSDan Willemsen 168*1c12ee1eSDan Willemsen case text.FieldNumber: 169*1c12ee1eSDan Willemsen isFieldNumberName = true 170*1c12ee1eSDan Willemsen num := protoreflect.FieldNumber(tok.FieldNumber()) 171*1c12ee1eSDan Willemsen if !num.IsValid() { 172*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "invalid field number: %d", num) 173*1c12ee1eSDan Willemsen } 174*1c12ee1eSDan Willemsen fd = fieldDescs.ByNumber(num) 175*1c12ee1eSDan Willemsen if fd == nil { 176*1c12ee1eSDan Willemsen xt, xtErr = d.opts.Resolver.FindExtensionByNumber(messageDesc.FullName(), num) 177*1c12ee1eSDan Willemsen } 178*1c12ee1eSDan Willemsen } 179*1c12ee1eSDan Willemsen 180*1c12ee1eSDan Willemsen if xt != nil { 181*1c12ee1eSDan Willemsen fd = xt.TypeDescriptor() 182*1c12ee1eSDan Willemsen if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() { 183*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName()) 184*1c12ee1eSDan Willemsen } 185*1c12ee1eSDan Willemsen } else if xtErr != nil && xtErr != protoregistry.NotFound { 186*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr) 187*1c12ee1eSDan Willemsen } 188*1c12ee1eSDan Willemsen if flags.ProtoLegacy { 189*1c12ee1eSDan Willemsen if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { 190*1c12ee1eSDan Willemsen fd = nil // reset since the weak reference is not linked in 191*1c12ee1eSDan Willemsen } 192*1c12ee1eSDan Willemsen } 193*1c12ee1eSDan Willemsen 194*1c12ee1eSDan Willemsen // Handle unknown fields. 195*1c12ee1eSDan Willemsen if fd == nil { 196*1c12ee1eSDan Willemsen if d.opts.DiscardUnknown || messageDesc.ReservedNames().Has(name) { 197*1c12ee1eSDan Willemsen d.skipValue() 198*1c12ee1eSDan Willemsen continue 199*1c12ee1eSDan Willemsen } 200*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "unknown field: %v", tok.RawString()) 201*1c12ee1eSDan Willemsen } 202*1c12ee1eSDan Willemsen 203*1c12ee1eSDan Willemsen // Handle fields identified by field number. 204*1c12ee1eSDan Willemsen if isFieldNumberName { 205*1c12ee1eSDan Willemsen // TODO: Add an option to permit parsing field numbers. 206*1c12ee1eSDan Willemsen // 207*1c12ee1eSDan Willemsen // This requires careful thought as the MarshalOptions.EmitUnknown 208*1c12ee1eSDan Willemsen // option allows formatting unknown fields as the field number and the 209*1c12ee1eSDan Willemsen // best-effort textual representation of the field value. In that case, 210*1c12ee1eSDan Willemsen // it may not be possible to unmarshal the value from a parser that does 211*1c12ee1eSDan Willemsen // have information about the unknown field. 212*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "cannot specify field by number: %v", tok.RawString()) 213*1c12ee1eSDan Willemsen } 214*1c12ee1eSDan Willemsen 215*1c12ee1eSDan Willemsen switch { 216*1c12ee1eSDan Willemsen case fd.IsList(): 217*1c12ee1eSDan Willemsen kind := fd.Kind() 218*1c12ee1eSDan Willemsen if kind != protoreflect.MessageKind && kind != protoreflect.GroupKind && !tok.HasSeparator() { 219*1c12ee1eSDan Willemsen return d.syntaxError(tok.Pos(), "missing field separator :") 220*1c12ee1eSDan Willemsen } 221*1c12ee1eSDan Willemsen 222*1c12ee1eSDan Willemsen list := m.Mutable(fd).List() 223*1c12ee1eSDan Willemsen if err := d.unmarshalList(fd, list); err != nil { 224*1c12ee1eSDan Willemsen return err 225*1c12ee1eSDan Willemsen } 226*1c12ee1eSDan Willemsen 227*1c12ee1eSDan Willemsen case fd.IsMap(): 228*1c12ee1eSDan Willemsen mmap := m.Mutable(fd).Map() 229*1c12ee1eSDan Willemsen if err := d.unmarshalMap(fd, mmap); err != nil { 230*1c12ee1eSDan Willemsen return err 231*1c12ee1eSDan Willemsen } 232*1c12ee1eSDan Willemsen 233*1c12ee1eSDan Willemsen default: 234*1c12ee1eSDan Willemsen kind := fd.Kind() 235*1c12ee1eSDan Willemsen if kind != protoreflect.MessageKind && kind != protoreflect.GroupKind && !tok.HasSeparator() { 236*1c12ee1eSDan Willemsen return d.syntaxError(tok.Pos(), "missing field separator :") 237*1c12ee1eSDan Willemsen } 238*1c12ee1eSDan Willemsen 239*1c12ee1eSDan Willemsen // If field is a oneof, check if it has already been set. 240*1c12ee1eSDan Willemsen if od := fd.ContainingOneof(); od != nil { 241*1c12ee1eSDan Willemsen idx := uint64(od.Index()) 242*1c12ee1eSDan Willemsen if seenOneofs.Has(idx) { 243*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "error parsing %q, oneof %v is already set", tok.RawString(), od.FullName()) 244*1c12ee1eSDan Willemsen } 245*1c12ee1eSDan Willemsen seenOneofs.Set(idx) 246*1c12ee1eSDan Willemsen } 247*1c12ee1eSDan Willemsen 248*1c12ee1eSDan Willemsen num := uint64(fd.Number()) 249*1c12ee1eSDan Willemsen if seenNums.Has(num) { 250*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "non-repeated field %q is repeated", tok.RawString()) 251*1c12ee1eSDan Willemsen } 252*1c12ee1eSDan Willemsen 253*1c12ee1eSDan Willemsen if err := d.unmarshalSingular(fd, m); err != nil { 254*1c12ee1eSDan Willemsen return err 255*1c12ee1eSDan Willemsen } 256*1c12ee1eSDan Willemsen seenNums.Set(num) 257*1c12ee1eSDan Willemsen } 258*1c12ee1eSDan Willemsen } 259*1c12ee1eSDan Willemsen 260*1c12ee1eSDan Willemsen return nil 261*1c12ee1eSDan Willemsen} 262*1c12ee1eSDan Willemsen 263*1c12ee1eSDan Willemsen// unmarshalSingular unmarshals a non-repeated field value specified by the 264*1c12ee1eSDan Willemsen// given FieldDescriptor. 265*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalSingular(fd protoreflect.FieldDescriptor, m protoreflect.Message) error { 266*1c12ee1eSDan Willemsen var val protoreflect.Value 267*1c12ee1eSDan Willemsen var err error 268*1c12ee1eSDan Willemsen switch fd.Kind() { 269*1c12ee1eSDan Willemsen case protoreflect.MessageKind, protoreflect.GroupKind: 270*1c12ee1eSDan Willemsen val = m.NewField(fd) 271*1c12ee1eSDan Willemsen err = d.unmarshalMessage(val.Message(), true) 272*1c12ee1eSDan Willemsen default: 273*1c12ee1eSDan Willemsen val, err = d.unmarshalScalar(fd) 274*1c12ee1eSDan Willemsen } 275*1c12ee1eSDan Willemsen if err == nil { 276*1c12ee1eSDan Willemsen m.Set(fd, val) 277*1c12ee1eSDan Willemsen } 278*1c12ee1eSDan Willemsen return err 279*1c12ee1eSDan Willemsen} 280*1c12ee1eSDan Willemsen 281*1c12ee1eSDan Willemsen// unmarshalScalar unmarshals a scalar/enum protoreflect.Value specified by the 282*1c12ee1eSDan Willemsen// given FieldDescriptor. 283*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { 284*1c12ee1eSDan Willemsen tok, err := d.Read() 285*1c12ee1eSDan Willemsen if err != nil { 286*1c12ee1eSDan Willemsen return protoreflect.Value{}, err 287*1c12ee1eSDan Willemsen } 288*1c12ee1eSDan Willemsen 289*1c12ee1eSDan Willemsen if tok.Kind() != text.Scalar { 290*1c12ee1eSDan Willemsen return protoreflect.Value{}, d.unexpectedTokenError(tok) 291*1c12ee1eSDan Willemsen } 292*1c12ee1eSDan Willemsen 293*1c12ee1eSDan Willemsen kind := fd.Kind() 294*1c12ee1eSDan Willemsen switch kind { 295*1c12ee1eSDan Willemsen case protoreflect.BoolKind: 296*1c12ee1eSDan Willemsen if b, ok := tok.Bool(); ok { 297*1c12ee1eSDan Willemsen return protoreflect.ValueOfBool(b), nil 298*1c12ee1eSDan Willemsen } 299*1c12ee1eSDan Willemsen 300*1c12ee1eSDan Willemsen case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: 301*1c12ee1eSDan Willemsen if n, ok := tok.Int32(); ok { 302*1c12ee1eSDan Willemsen return protoreflect.ValueOfInt32(n), nil 303*1c12ee1eSDan Willemsen } 304*1c12ee1eSDan Willemsen 305*1c12ee1eSDan Willemsen case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: 306*1c12ee1eSDan Willemsen if n, ok := tok.Int64(); ok { 307*1c12ee1eSDan Willemsen return protoreflect.ValueOfInt64(n), nil 308*1c12ee1eSDan Willemsen } 309*1c12ee1eSDan Willemsen 310*1c12ee1eSDan Willemsen case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: 311*1c12ee1eSDan Willemsen if n, ok := tok.Uint32(); ok { 312*1c12ee1eSDan Willemsen return protoreflect.ValueOfUint32(n), nil 313*1c12ee1eSDan Willemsen } 314*1c12ee1eSDan Willemsen 315*1c12ee1eSDan Willemsen case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: 316*1c12ee1eSDan Willemsen if n, ok := tok.Uint64(); ok { 317*1c12ee1eSDan Willemsen return protoreflect.ValueOfUint64(n), nil 318*1c12ee1eSDan Willemsen } 319*1c12ee1eSDan Willemsen 320*1c12ee1eSDan Willemsen case protoreflect.FloatKind: 321*1c12ee1eSDan Willemsen if n, ok := tok.Float32(); ok { 322*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat32(n), nil 323*1c12ee1eSDan Willemsen } 324*1c12ee1eSDan Willemsen 325*1c12ee1eSDan Willemsen case protoreflect.DoubleKind: 326*1c12ee1eSDan Willemsen if n, ok := tok.Float64(); ok { 327*1c12ee1eSDan Willemsen return protoreflect.ValueOfFloat64(n), nil 328*1c12ee1eSDan Willemsen } 329*1c12ee1eSDan Willemsen 330*1c12ee1eSDan Willemsen case protoreflect.StringKind: 331*1c12ee1eSDan Willemsen if s, ok := tok.String(); ok { 332*1c12ee1eSDan Willemsen if strs.EnforceUTF8(fd) && !utf8.ValidString(s) { 333*1c12ee1eSDan Willemsen return protoreflect.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8") 334*1c12ee1eSDan Willemsen } 335*1c12ee1eSDan Willemsen return protoreflect.ValueOfString(s), nil 336*1c12ee1eSDan Willemsen } 337*1c12ee1eSDan Willemsen 338*1c12ee1eSDan Willemsen case protoreflect.BytesKind: 339*1c12ee1eSDan Willemsen if b, ok := tok.String(); ok { 340*1c12ee1eSDan Willemsen return protoreflect.ValueOfBytes([]byte(b)), nil 341*1c12ee1eSDan Willemsen } 342*1c12ee1eSDan Willemsen 343*1c12ee1eSDan Willemsen case protoreflect.EnumKind: 344*1c12ee1eSDan Willemsen if lit, ok := tok.Enum(); ok { 345*1c12ee1eSDan Willemsen // Lookup EnumNumber based on name. 346*1c12ee1eSDan Willemsen if enumVal := fd.Enum().Values().ByName(protoreflect.Name(lit)); enumVal != nil { 347*1c12ee1eSDan Willemsen return protoreflect.ValueOfEnum(enumVal.Number()), nil 348*1c12ee1eSDan Willemsen } 349*1c12ee1eSDan Willemsen } 350*1c12ee1eSDan Willemsen if num, ok := tok.Int32(); ok { 351*1c12ee1eSDan Willemsen return protoreflect.ValueOfEnum(protoreflect.EnumNumber(num)), nil 352*1c12ee1eSDan Willemsen } 353*1c12ee1eSDan Willemsen 354*1c12ee1eSDan Willemsen default: 355*1c12ee1eSDan Willemsen panic(fmt.Sprintf("invalid scalar kind %v", kind)) 356*1c12ee1eSDan Willemsen } 357*1c12ee1eSDan Willemsen 358*1c12ee1eSDan Willemsen return protoreflect.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString()) 359*1c12ee1eSDan Willemsen} 360*1c12ee1eSDan Willemsen 361*1c12ee1eSDan Willemsen// unmarshalList unmarshals into given protoreflect.List. A list value can 362*1c12ee1eSDan Willemsen// either be in [] syntax or simply just a single scalar/message value. 363*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalList(fd protoreflect.FieldDescriptor, list protoreflect.List) error { 364*1c12ee1eSDan Willemsen tok, err := d.Peek() 365*1c12ee1eSDan Willemsen if err != nil { 366*1c12ee1eSDan Willemsen return err 367*1c12ee1eSDan Willemsen } 368*1c12ee1eSDan Willemsen 369*1c12ee1eSDan Willemsen switch fd.Kind() { 370*1c12ee1eSDan Willemsen case protoreflect.MessageKind, protoreflect.GroupKind: 371*1c12ee1eSDan Willemsen switch tok.Kind() { 372*1c12ee1eSDan Willemsen case text.ListOpen: 373*1c12ee1eSDan Willemsen d.Read() 374*1c12ee1eSDan Willemsen for { 375*1c12ee1eSDan Willemsen tok, err := d.Peek() 376*1c12ee1eSDan Willemsen if err != nil { 377*1c12ee1eSDan Willemsen return err 378*1c12ee1eSDan Willemsen } 379*1c12ee1eSDan Willemsen 380*1c12ee1eSDan Willemsen switch tok.Kind() { 381*1c12ee1eSDan Willemsen case text.ListClose: 382*1c12ee1eSDan Willemsen d.Read() 383*1c12ee1eSDan Willemsen return nil 384*1c12ee1eSDan Willemsen case text.MessageOpen: 385*1c12ee1eSDan Willemsen pval := list.NewElement() 386*1c12ee1eSDan Willemsen if err := d.unmarshalMessage(pval.Message(), true); err != nil { 387*1c12ee1eSDan Willemsen return err 388*1c12ee1eSDan Willemsen } 389*1c12ee1eSDan Willemsen list.Append(pval) 390*1c12ee1eSDan Willemsen default: 391*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 392*1c12ee1eSDan Willemsen } 393*1c12ee1eSDan Willemsen } 394*1c12ee1eSDan Willemsen 395*1c12ee1eSDan Willemsen case text.MessageOpen: 396*1c12ee1eSDan Willemsen pval := list.NewElement() 397*1c12ee1eSDan Willemsen if err := d.unmarshalMessage(pval.Message(), true); err != nil { 398*1c12ee1eSDan Willemsen return err 399*1c12ee1eSDan Willemsen } 400*1c12ee1eSDan Willemsen list.Append(pval) 401*1c12ee1eSDan Willemsen return nil 402*1c12ee1eSDan Willemsen } 403*1c12ee1eSDan Willemsen 404*1c12ee1eSDan Willemsen default: 405*1c12ee1eSDan Willemsen switch tok.Kind() { 406*1c12ee1eSDan Willemsen case text.ListOpen: 407*1c12ee1eSDan Willemsen d.Read() 408*1c12ee1eSDan Willemsen for { 409*1c12ee1eSDan Willemsen tok, err := d.Peek() 410*1c12ee1eSDan Willemsen if err != nil { 411*1c12ee1eSDan Willemsen return err 412*1c12ee1eSDan Willemsen } 413*1c12ee1eSDan Willemsen 414*1c12ee1eSDan Willemsen switch tok.Kind() { 415*1c12ee1eSDan Willemsen case text.ListClose: 416*1c12ee1eSDan Willemsen d.Read() 417*1c12ee1eSDan Willemsen return nil 418*1c12ee1eSDan Willemsen case text.Scalar: 419*1c12ee1eSDan Willemsen pval, err := d.unmarshalScalar(fd) 420*1c12ee1eSDan Willemsen if err != nil { 421*1c12ee1eSDan Willemsen return err 422*1c12ee1eSDan Willemsen } 423*1c12ee1eSDan Willemsen list.Append(pval) 424*1c12ee1eSDan Willemsen default: 425*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 426*1c12ee1eSDan Willemsen } 427*1c12ee1eSDan Willemsen } 428*1c12ee1eSDan Willemsen 429*1c12ee1eSDan Willemsen case text.Scalar: 430*1c12ee1eSDan Willemsen pval, err := d.unmarshalScalar(fd) 431*1c12ee1eSDan Willemsen if err != nil { 432*1c12ee1eSDan Willemsen return err 433*1c12ee1eSDan Willemsen } 434*1c12ee1eSDan Willemsen list.Append(pval) 435*1c12ee1eSDan Willemsen return nil 436*1c12ee1eSDan Willemsen } 437*1c12ee1eSDan Willemsen } 438*1c12ee1eSDan Willemsen 439*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 440*1c12ee1eSDan Willemsen} 441*1c12ee1eSDan Willemsen 442*1c12ee1eSDan Willemsen// unmarshalMap unmarshals into given protoreflect.Map. A map value is a 443*1c12ee1eSDan Willemsen// textproto message containing {key: <kvalue>, value: <mvalue>}. 444*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMap(fd protoreflect.FieldDescriptor, mmap protoreflect.Map) error { 445*1c12ee1eSDan Willemsen // Determine ahead whether map entry is a scalar type or a message type in 446*1c12ee1eSDan Willemsen // order to call the appropriate unmarshalMapValue func inside 447*1c12ee1eSDan Willemsen // unmarshalMapEntry. 448*1c12ee1eSDan Willemsen var unmarshalMapValue func() (protoreflect.Value, error) 449*1c12ee1eSDan Willemsen switch fd.MapValue().Kind() { 450*1c12ee1eSDan Willemsen case protoreflect.MessageKind, protoreflect.GroupKind: 451*1c12ee1eSDan Willemsen unmarshalMapValue = func() (protoreflect.Value, error) { 452*1c12ee1eSDan Willemsen pval := mmap.NewValue() 453*1c12ee1eSDan Willemsen if err := d.unmarshalMessage(pval.Message(), true); err != nil { 454*1c12ee1eSDan Willemsen return protoreflect.Value{}, err 455*1c12ee1eSDan Willemsen } 456*1c12ee1eSDan Willemsen return pval, nil 457*1c12ee1eSDan Willemsen } 458*1c12ee1eSDan Willemsen default: 459*1c12ee1eSDan Willemsen unmarshalMapValue = func() (protoreflect.Value, error) { 460*1c12ee1eSDan Willemsen return d.unmarshalScalar(fd.MapValue()) 461*1c12ee1eSDan Willemsen } 462*1c12ee1eSDan Willemsen } 463*1c12ee1eSDan Willemsen 464*1c12ee1eSDan Willemsen tok, err := d.Read() 465*1c12ee1eSDan Willemsen if err != nil { 466*1c12ee1eSDan Willemsen return err 467*1c12ee1eSDan Willemsen } 468*1c12ee1eSDan Willemsen switch tok.Kind() { 469*1c12ee1eSDan Willemsen case text.MessageOpen: 470*1c12ee1eSDan Willemsen return d.unmarshalMapEntry(fd, mmap, unmarshalMapValue) 471*1c12ee1eSDan Willemsen 472*1c12ee1eSDan Willemsen case text.ListOpen: 473*1c12ee1eSDan Willemsen for { 474*1c12ee1eSDan Willemsen tok, err := d.Read() 475*1c12ee1eSDan Willemsen if err != nil { 476*1c12ee1eSDan Willemsen return err 477*1c12ee1eSDan Willemsen } 478*1c12ee1eSDan Willemsen switch tok.Kind() { 479*1c12ee1eSDan Willemsen case text.ListClose: 480*1c12ee1eSDan Willemsen return nil 481*1c12ee1eSDan Willemsen case text.MessageOpen: 482*1c12ee1eSDan Willemsen if err := d.unmarshalMapEntry(fd, mmap, unmarshalMapValue); err != nil { 483*1c12ee1eSDan Willemsen return err 484*1c12ee1eSDan Willemsen } 485*1c12ee1eSDan Willemsen default: 486*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 487*1c12ee1eSDan Willemsen } 488*1c12ee1eSDan Willemsen } 489*1c12ee1eSDan Willemsen 490*1c12ee1eSDan Willemsen default: 491*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 492*1c12ee1eSDan Willemsen } 493*1c12ee1eSDan Willemsen} 494*1c12ee1eSDan Willemsen 495*1c12ee1eSDan Willemsen// unmarshalMap unmarshals into given protoreflect.Map. A map value is a 496*1c12ee1eSDan Willemsen// textproto message containing {key: <kvalue>, value: <mvalue>}. 497*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMapEntry(fd protoreflect.FieldDescriptor, mmap protoreflect.Map, unmarshalMapValue func() (protoreflect.Value, error)) error { 498*1c12ee1eSDan Willemsen var key protoreflect.MapKey 499*1c12ee1eSDan Willemsen var pval protoreflect.Value 500*1c12ee1eSDan WillemsenLoop: 501*1c12ee1eSDan Willemsen for { 502*1c12ee1eSDan Willemsen // Read field name. 503*1c12ee1eSDan Willemsen tok, err := d.Read() 504*1c12ee1eSDan Willemsen if err != nil { 505*1c12ee1eSDan Willemsen return err 506*1c12ee1eSDan Willemsen } 507*1c12ee1eSDan Willemsen switch tok.Kind() { 508*1c12ee1eSDan Willemsen case text.Name: 509*1c12ee1eSDan Willemsen if tok.NameKind() != text.IdentName { 510*1c12ee1eSDan Willemsen if !d.opts.DiscardUnknown { 511*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "unknown map entry field %q", tok.RawString()) 512*1c12ee1eSDan Willemsen } 513*1c12ee1eSDan Willemsen d.skipValue() 514*1c12ee1eSDan Willemsen continue Loop 515*1c12ee1eSDan Willemsen } 516*1c12ee1eSDan Willemsen // Continue below. 517*1c12ee1eSDan Willemsen case text.MessageClose: 518*1c12ee1eSDan Willemsen break Loop 519*1c12ee1eSDan Willemsen default: 520*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 521*1c12ee1eSDan Willemsen } 522*1c12ee1eSDan Willemsen 523*1c12ee1eSDan Willemsen switch name := protoreflect.Name(tok.IdentName()); name { 524*1c12ee1eSDan Willemsen case genid.MapEntry_Key_field_name: 525*1c12ee1eSDan Willemsen if !tok.HasSeparator() { 526*1c12ee1eSDan Willemsen return d.syntaxError(tok.Pos(), "missing field separator :") 527*1c12ee1eSDan Willemsen } 528*1c12ee1eSDan Willemsen if key.IsValid() { 529*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "map entry %q cannot be repeated", name) 530*1c12ee1eSDan Willemsen } 531*1c12ee1eSDan Willemsen val, err := d.unmarshalScalar(fd.MapKey()) 532*1c12ee1eSDan Willemsen if err != nil { 533*1c12ee1eSDan Willemsen return err 534*1c12ee1eSDan Willemsen } 535*1c12ee1eSDan Willemsen key = val.MapKey() 536*1c12ee1eSDan Willemsen 537*1c12ee1eSDan Willemsen case genid.MapEntry_Value_field_name: 538*1c12ee1eSDan Willemsen if kind := fd.MapValue().Kind(); (kind != protoreflect.MessageKind) && (kind != protoreflect.GroupKind) { 539*1c12ee1eSDan Willemsen if !tok.HasSeparator() { 540*1c12ee1eSDan Willemsen return d.syntaxError(tok.Pos(), "missing field separator :") 541*1c12ee1eSDan Willemsen } 542*1c12ee1eSDan Willemsen } 543*1c12ee1eSDan Willemsen if pval.IsValid() { 544*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "map entry %q cannot be repeated", name) 545*1c12ee1eSDan Willemsen } 546*1c12ee1eSDan Willemsen pval, err = unmarshalMapValue() 547*1c12ee1eSDan Willemsen if err != nil { 548*1c12ee1eSDan Willemsen return err 549*1c12ee1eSDan Willemsen } 550*1c12ee1eSDan Willemsen 551*1c12ee1eSDan Willemsen default: 552*1c12ee1eSDan Willemsen if !d.opts.DiscardUnknown { 553*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "unknown map entry field %q", name) 554*1c12ee1eSDan Willemsen } 555*1c12ee1eSDan Willemsen d.skipValue() 556*1c12ee1eSDan Willemsen } 557*1c12ee1eSDan Willemsen } 558*1c12ee1eSDan Willemsen 559*1c12ee1eSDan Willemsen if !key.IsValid() { 560*1c12ee1eSDan Willemsen key = fd.MapKey().Default().MapKey() 561*1c12ee1eSDan Willemsen } 562*1c12ee1eSDan Willemsen if !pval.IsValid() { 563*1c12ee1eSDan Willemsen switch fd.MapValue().Kind() { 564*1c12ee1eSDan Willemsen case protoreflect.MessageKind, protoreflect.GroupKind: 565*1c12ee1eSDan Willemsen // If value field is not set for message/group types, construct an 566*1c12ee1eSDan Willemsen // empty one as default. 567*1c12ee1eSDan Willemsen pval = mmap.NewValue() 568*1c12ee1eSDan Willemsen default: 569*1c12ee1eSDan Willemsen pval = fd.MapValue().Default() 570*1c12ee1eSDan Willemsen } 571*1c12ee1eSDan Willemsen } 572*1c12ee1eSDan Willemsen mmap.Set(key, pval) 573*1c12ee1eSDan Willemsen return nil 574*1c12ee1eSDan Willemsen} 575*1c12ee1eSDan Willemsen 576*1c12ee1eSDan Willemsen// unmarshalAny unmarshals an Any textproto. It can either be in expanded form 577*1c12ee1eSDan Willemsen// or non-expanded form. 578*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalAny(m protoreflect.Message, checkDelims bool) error { 579*1c12ee1eSDan Willemsen var typeURL string 580*1c12ee1eSDan Willemsen var bValue []byte 581*1c12ee1eSDan Willemsen var seenTypeUrl bool 582*1c12ee1eSDan Willemsen var seenValue bool 583*1c12ee1eSDan Willemsen var isExpanded bool 584*1c12ee1eSDan Willemsen 585*1c12ee1eSDan Willemsen if checkDelims { 586*1c12ee1eSDan Willemsen tok, err := d.Read() 587*1c12ee1eSDan Willemsen if err != nil { 588*1c12ee1eSDan Willemsen return err 589*1c12ee1eSDan Willemsen } 590*1c12ee1eSDan Willemsen 591*1c12ee1eSDan Willemsen if tok.Kind() != text.MessageOpen { 592*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 593*1c12ee1eSDan Willemsen } 594*1c12ee1eSDan Willemsen } 595*1c12ee1eSDan Willemsen 596*1c12ee1eSDan WillemsenLoop: 597*1c12ee1eSDan Willemsen for { 598*1c12ee1eSDan Willemsen // Read field name. Can only have 3 possible field names, i.e. type_url, 599*1c12ee1eSDan Willemsen // value and type URL name inside []. 600*1c12ee1eSDan Willemsen tok, err := d.Read() 601*1c12ee1eSDan Willemsen if err != nil { 602*1c12ee1eSDan Willemsen return err 603*1c12ee1eSDan Willemsen } 604*1c12ee1eSDan Willemsen if typ := tok.Kind(); typ != text.Name { 605*1c12ee1eSDan Willemsen if checkDelims { 606*1c12ee1eSDan Willemsen if typ == text.MessageClose { 607*1c12ee1eSDan Willemsen break Loop 608*1c12ee1eSDan Willemsen } 609*1c12ee1eSDan Willemsen } else if typ == text.EOF { 610*1c12ee1eSDan Willemsen break Loop 611*1c12ee1eSDan Willemsen } 612*1c12ee1eSDan Willemsen return d.unexpectedTokenError(tok) 613*1c12ee1eSDan Willemsen } 614*1c12ee1eSDan Willemsen 615*1c12ee1eSDan Willemsen switch tok.NameKind() { 616*1c12ee1eSDan Willemsen case text.IdentName: 617*1c12ee1eSDan Willemsen // Both type_url and value fields require field separator :. 618*1c12ee1eSDan Willemsen if !tok.HasSeparator() { 619*1c12ee1eSDan Willemsen return d.syntaxError(tok.Pos(), "missing field separator :") 620*1c12ee1eSDan Willemsen } 621*1c12ee1eSDan Willemsen 622*1c12ee1eSDan Willemsen switch name := protoreflect.Name(tok.IdentName()); name { 623*1c12ee1eSDan Willemsen case genid.Any_TypeUrl_field_name: 624*1c12ee1eSDan Willemsen if seenTypeUrl { 625*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "duplicate %v field", genid.Any_TypeUrl_field_fullname) 626*1c12ee1eSDan Willemsen } 627*1c12ee1eSDan Willemsen if isExpanded { 628*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) 629*1c12ee1eSDan Willemsen } 630*1c12ee1eSDan Willemsen tok, err := d.Read() 631*1c12ee1eSDan Willemsen if err != nil { 632*1c12ee1eSDan Willemsen return err 633*1c12ee1eSDan Willemsen } 634*1c12ee1eSDan Willemsen var ok bool 635*1c12ee1eSDan Willemsen typeURL, ok = tok.String() 636*1c12ee1eSDan Willemsen if !ok { 637*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_TypeUrl_field_fullname, tok.RawString()) 638*1c12ee1eSDan Willemsen } 639*1c12ee1eSDan Willemsen seenTypeUrl = true 640*1c12ee1eSDan Willemsen 641*1c12ee1eSDan Willemsen case genid.Any_Value_field_name: 642*1c12ee1eSDan Willemsen if seenValue { 643*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "duplicate %v field", genid.Any_Value_field_fullname) 644*1c12ee1eSDan Willemsen } 645*1c12ee1eSDan Willemsen if isExpanded { 646*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) 647*1c12ee1eSDan Willemsen } 648*1c12ee1eSDan Willemsen tok, err := d.Read() 649*1c12ee1eSDan Willemsen if err != nil { 650*1c12ee1eSDan Willemsen return err 651*1c12ee1eSDan Willemsen } 652*1c12ee1eSDan Willemsen s, ok := tok.String() 653*1c12ee1eSDan Willemsen if !ok { 654*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_Value_field_fullname, tok.RawString()) 655*1c12ee1eSDan Willemsen } 656*1c12ee1eSDan Willemsen bValue = []byte(s) 657*1c12ee1eSDan Willemsen seenValue = true 658*1c12ee1eSDan Willemsen 659*1c12ee1eSDan Willemsen default: 660*1c12ee1eSDan Willemsen if !d.opts.DiscardUnknown { 661*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname) 662*1c12ee1eSDan Willemsen } 663*1c12ee1eSDan Willemsen } 664*1c12ee1eSDan Willemsen 665*1c12ee1eSDan Willemsen case text.TypeName: 666*1c12ee1eSDan Willemsen if isExpanded { 667*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "cannot have more than one type") 668*1c12ee1eSDan Willemsen } 669*1c12ee1eSDan Willemsen if seenTypeUrl { 670*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "conflict with type_url field") 671*1c12ee1eSDan Willemsen } 672*1c12ee1eSDan Willemsen typeURL = tok.TypeName() 673*1c12ee1eSDan Willemsen var err error 674*1c12ee1eSDan Willemsen bValue, err = d.unmarshalExpandedAny(typeURL, tok.Pos()) 675*1c12ee1eSDan Willemsen if err != nil { 676*1c12ee1eSDan Willemsen return err 677*1c12ee1eSDan Willemsen } 678*1c12ee1eSDan Willemsen isExpanded = true 679*1c12ee1eSDan Willemsen 680*1c12ee1eSDan Willemsen default: 681*1c12ee1eSDan Willemsen if !d.opts.DiscardUnknown { 682*1c12ee1eSDan Willemsen return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname) 683*1c12ee1eSDan Willemsen } 684*1c12ee1eSDan Willemsen } 685*1c12ee1eSDan Willemsen } 686*1c12ee1eSDan Willemsen 687*1c12ee1eSDan Willemsen fds := m.Descriptor().Fields() 688*1c12ee1eSDan Willemsen if len(typeURL) > 0 { 689*1c12ee1eSDan Willemsen m.Set(fds.ByNumber(genid.Any_TypeUrl_field_number), protoreflect.ValueOfString(typeURL)) 690*1c12ee1eSDan Willemsen } 691*1c12ee1eSDan Willemsen if len(bValue) > 0 { 692*1c12ee1eSDan Willemsen m.Set(fds.ByNumber(genid.Any_Value_field_number), protoreflect.ValueOfBytes(bValue)) 693*1c12ee1eSDan Willemsen } 694*1c12ee1eSDan Willemsen return nil 695*1c12ee1eSDan Willemsen} 696*1c12ee1eSDan Willemsen 697*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalExpandedAny(typeURL string, pos int) ([]byte, error) { 698*1c12ee1eSDan Willemsen mt, err := d.opts.Resolver.FindMessageByURL(typeURL) 699*1c12ee1eSDan Willemsen if err != nil { 700*1c12ee1eSDan Willemsen return nil, d.newError(pos, "unable to resolve message [%v]: %v", typeURL, err) 701*1c12ee1eSDan Willemsen } 702*1c12ee1eSDan Willemsen // Create new message for the embedded message type and unmarshal the value 703*1c12ee1eSDan Willemsen // field into it. 704*1c12ee1eSDan Willemsen m := mt.New() 705*1c12ee1eSDan Willemsen if err := d.unmarshalMessage(m, true); err != nil { 706*1c12ee1eSDan Willemsen return nil, err 707*1c12ee1eSDan Willemsen } 708*1c12ee1eSDan Willemsen // Serialize the embedded message and return the resulting bytes. 709*1c12ee1eSDan Willemsen b, err := proto.MarshalOptions{ 710*1c12ee1eSDan Willemsen AllowPartial: true, // Never check required fields inside an Any. 711*1c12ee1eSDan Willemsen Deterministic: true, 712*1c12ee1eSDan Willemsen }.Marshal(m.Interface()) 713*1c12ee1eSDan Willemsen if err != nil { 714*1c12ee1eSDan Willemsen return nil, d.newError(pos, "error in marshaling message into Any.value: %v", err) 715*1c12ee1eSDan Willemsen } 716*1c12ee1eSDan Willemsen return b, nil 717*1c12ee1eSDan Willemsen} 718*1c12ee1eSDan Willemsen 719*1c12ee1eSDan Willemsen// skipValue makes the decoder parse a field value in order to advance the read 720*1c12ee1eSDan Willemsen// to the next field. It relies on Read returning an error if the types are not 721*1c12ee1eSDan Willemsen// in valid sequence. 722*1c12ee1eSDan Willemsenfunc (d decoder) skipValue() error { 723*1c12ee1eSDan Willemsen tok, err := d.Read() 724*1c12ee1eSDan Willemsen if err != nil { 725*1c12ee1eSDan Willemsen return err 726*1c12ee1eSDan Willemsen } 727*1c12ee1eSDan Willemsen // Only need to continue reading for messages and lists. 728*1c12ee1eSDan Willemsen switch tok.Kind() { 729*1c12ee1eSDan Willemsen case text.MessageOpen: 730*1c12ee1eSDan Willemsen return d.skipMessageValue() 731*1c12ee1eSDan Willemsen 732*1c12ee1eSDan Willemsen case text.ListOpen: 733*1c12ee1eSDan Willemsen for { 734*1c12ee1eSDan Willemsen tok, err := d.Read() 735*1c12ee1eSDan Willemsen if err != nil { 736*1c12ee1eSDan Willemsen return err 737*1c12ee1eSDan Willemsen } 738*1c12ee1eSDan Willemsen switch tok.Kind() { 739*1c12ee1eSDan Willemsen case text.ListClose: 740*1c12ee1eSDan Willemsen return nil 741*1c12ee1eSDan Willemsen case text.MessageOpen: 742*1c12ee1eSDan Willemsen return d.skipMessageValue() 743*1c12ee1eSDan Willemsen default: 744*1c12ee1eSDan Willemsen // Skip items. This will not validate whether skipped values are 745*1c12ee1eSDan Willemsen // of the same type or not, same behavior as C++ 746*1c12ee1eSDan Willemsen // TextFormat::Parser::AllowUnknownField(true) version 3.8.0. 747*1c12ee1eSDan Willemsen } 748*1c12ee1eSDan Willemsen } 749*1c12ee1eSDan Willemsen } 750*1c12ee1eSDan Willemsen return nil 751*1c12ee1eSDan Willemsen} 752*1c12ee1eSDan Willemsen 753*1c12ee1eSDan Willemsen// skipMessageValue makes the decoder parse and skip over all fields in a 754*1c12ee1eSDan Willemsen// message. It assumes that the previous read type is MessageOpen. 755*1c12ee1eSDan Willemsenfunc (d decoder) skipMessageValue() error { 756*1c12ee1eSDan Willemsen for { 757*1c12ee1eSDan Willemsen tok, err := d.Read() 758*1c12ee1eSDan Willemsen if err != nil { 759*1c12ee1eSDan Willemsen return err 760*1c12ee1eSDan Willemsen } 761*1c12ee1eSDan Willemsen switch tok.Kind() { 762*1c12ee1eSDan Willemsen case text.MessageClose: 763*1c12ee1eSDan Willemsen return nil 764*1c12ee1eSDan Willemsen case text.Name: 765*1c12ee1eSDan Willemsen if err := d.skipValue(); err != nil { 766*1c12ee1eSDan Willemsen return err 767*1c12ee1eSDan Willemsen } 768*1c12ee1eSDan Willemsen } 769*1c12ee1eSDan Willemsen } 770*1c12ee1eSDan Willemsen} 771