2018-12-06 15:28:53 -08:00
|
|
|
// Copyright 2018 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2019-05-14 12:44:37 -07:00
|
|
|
package prototext
|
2018-12-06 15:28:53 -08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-04-08 17:32:44 -07:00
|
|
|
"unicode/utf8"
|
2018-12-06 15:28:53 -08:00
|
|
|
|
2019-07-11 18:23:08 -07:00
|
|
|
"google.golang.org/protobuf/internal/encoding/messageset"
|
2019-05-13 23:55:40 -07:00
|
|
|
"google.golang.org/protobuf/internal/encoding/text"
|
|
|
|
"google.golang.org/protobuf/internal/errors"
|
2019-07-11 18:23:08 -07:00
|
|
|
"google.golang.org/protobuf/internal/flags"
|
2020-05-26 11:21:59 -07:00
|
|
|
"google.golang.org/protobuf/internal/genid"
|
2019-05-13 23:55:40 -07:00
|
|
|
"google.golang.org/protobuf/internal/pragma"
|
|
|
|
"google.golang.org/protobuf/internal/set"
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
"google.golang.org/protobuf/internal/strs"
|
2019-05-13 23:55:40 -07:00
|
|
|
"google.golang.org/protobuf/proto"
|
2022-05-24 05:12:23 +09:00
|
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
2019-05-13 23:55:40 -07:00
|
|
|
"google.golang.org/protobuf/reflect/protoregistry"
|
2018-12-06 15:28:53 -08:00
|
|
|
)
|
|
|
|
|
2021-04-12 13:48:27 -07:00
|
|
|
// Unmarshal reads the given []byte into the given [proto.Message].
|
2021-03-16 12:38:21 -07:00
|
|
|
// The provided message must be mutable (e.g., a non-nil pointer to a message).
|
2019-05-14 16:05:06 -07:00
|
|
|
func Unmarshal(b []byte, m proto.Message) error {
|
|
|
|
return UnmarshalOptions{}.Unmarshal(b, m)
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-03-26 16:26:22 -07:00
|
|
|
// UnmarshalOptions is a configurable textproto format unmarshaler.
|
2018-12-06 15:28:53 -08:00
|
|
|
type UnmarshalOptions struct {
|
|
|
|
pragma.NoUnkeyedLiterals
|
2018-12-18 18:04:31 -08:00
|
|
|
|
2019-03-26 16:26:22 -07:00
|
|
|
// AllowPartial accepts input for messages that will result in missing
|
|
|
|
// required fields. If AllowPartial is false (the default), Unmarshal will
|
|
|
|
// return error if there are any missing required fields.
|
|
|
|
AllowPartial bool
|
|
|
|
|
2019-09-15 00:17:39 -07:00
|
|
|
// DiscardUnknown specifies whether to ignore unknown fields when parsing.
|
|
|
|
// An unknown field is any field whose field name or field number does not
|
|
|
|
// resolve to any known or extension field in the message.
|
|
|
|
// By default, unmarshal rejects unknown fields as an error.
|
|
|
|
DiscardUnknown bool
|
|
|
|
|
2019-05-14 14:28:19 -07:00
|
|
|
// Resolver is used for looking up types when unmarshaling
|
|
|
|
// google.protobuf.Any messages or extension fields.
|
|
|
|
// If nil, this defaults to using protoregistry.GlobalTypes.
|
|
|
|
Resolver interface {
|
|
|
|
protoregistry.MessageTypeResolver
|
|
|
|
protoregistry.ExtensionTypeResolver
|
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2021-04-12 13:48:27 -07:00
|
|
|
// Unmarshal reads the given []byte and populates the given [proto.Message]
|
2021-03-16 12:38:21 -07:00
|
|
|
// using options in the UnmarshalOptions object.
|
|
|
|
// The provided message must be mutable (e.g., a non-nil pointer to a message).
|
2019-05-14 16:05:06 -07:00
|
|
|
func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
|
2020-05-14 15:29:58 -07:00
|
|
|
return o.unmarshal(b, m)
|
|
|
|
}
|
|
|
|
|
|
|
|
// unmarshal is a centralized function that all unmarshal operations go through.
|
|
|
|
// For profiling purposes, avoid changing the name of this function or
|
|
|
|
// introducing other code paths for unmarshal that do not go through this.
|
|
|
|
func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error {
|
2019-04-25 23:48:08 -07:00
|
|
|
proto.Reset(m)
|
2018-12-06 15:28:53 -08:00
|
|
|
|
2018-12-18 18:04:31 -08:00
|
|
|
if o.Resolver == nil {
|
|
|
|
o.Resolver = protoregistry.GlobalTypes
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
dec := decoder{text.NewDecoder(b), o}
|
|
|
|
if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil {
|
2018-12-06 15:28:53 -08:00
|
|
|
return err
|
|
|
|
}
|
2019-06-19 09:28:29 -07:00
|
|
|
if o.AllowPartial {
|
|
|
|
return nil
|
2019-04-05 13:31:40 -07:00
|
|
|
}
|
2020-02-20 10:05:37 -08:00
|
|
|
return proto.CheckInitialized(m)
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
type decoder struct {
|
|
|
|
*text.Decoder
|
|
|
|
opts UnmarshalOptions
|
|
|
|
}
|
|
|
|
|
|
|
|
// newError returns an error object with position info.
|
2024-05-15 13:11:52 +02:00
|
|
|
func (d decoder) newError(pos int, f string, x ...any) error {
|
2019-10-31 17:10:15 -07:00
|
|
|
line, column := d.Position(pos)
|
|
|
|
head := fmt.Sprintf("(line %d:%d): ", line, column)
|
|
|
|
return errors.New(head+f, x...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// unexpectedTokenError returns a syntax error for the given unexpected token.
|
|
|
|
func (d decoder) unexpectedTokenError(tok text.Token) error {
|
|
|
|
return d.syntaxError(tok.Pos(), "unexpected token: %s", tok.RawString())
|
|
|
|
}
|
|
|
|
|
|
|
|
// syntaxError returns a syntax error for given position.
|
2024-05-15 13:11:52 +02:00
|
|
|
func (d decoder) syntaxError(pos int, f string, x ...any) error {
|
2019-10-31 17:10:15 -07:00
|
|
|
line, column := d.Position(pos)
|
|
|
|
head := fmt.Sprintf("syntax error (line %d:%d): ", line, column)
|
|
|
|
return errors.New(head+f, x...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// unmarshalMessage unmarshals into the given protoreflect.Message.
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d decoder) unmarshalMessage(m protoreflect.Message, checkDelims bool) error {
|
2019-05-01 12:29:25 -07:00
|
|
|
messageDesc := m.Descriptor()
|
2019-08-08 13:31:59 -07:00
|
|
|
if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) {
|
2019-07-11 18:23:08 -07:00
|
|
|
return errors.New("no support for proto1 MessageSets")
|
|
|
|
}
|
2019-01-04 14:08:41 -08:00
|
|
|
|
2020-05-26 11:21:59 -07:00
|
|
|
if messageDesc.FullName() == genid.Any_message_fullname {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.unmarshalAny(m, checkDelims)
|
|
|
|
}
|
|
|
|
|
|
|
|
if checkDelims {
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if tok.Kind() != text.MessageOpen {
|
|
|
|
return d.unexpectedTokenError(tok)
|
|
|
|
}
|
2019-01-04 14:08:41 -08:00
|
|
|
}
|
|
|
|
|
2018-12-06 15:28:53 -08:00
|
|
|
var seenNums set.Ints
|
2019-04-02 20:19:36 -07:00
|
|
|
var seenOneofs set.Ints
|
2019-07-11 18:23:08 -07:00
|
|
|
fieldDescs := messageDesc.Fields()
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
for {
|
|
|
|
// Read field name.
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch typ := tok.Kind(); typ {
|
|
|
|
case text.Name:
|
|
|
|
// Continue below.
|
|
|
|
case text.EOF:
|
|
|
|
if checkDelims {
|
2020-02-06 18:43:12 -08:00
|
|
|
return text.ErrUnexpectedEOF
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
if checkDelims && typ == text.MessageClose {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return d.unexpectedTokenError(tok)
|
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
|
2019-09-15 00:17:39 -07:00
|
|
|
// Resolve the field descriptor.
|
2022-05-24 05:12:23 +09:00
|
|
|
var name protoreflect.Name
|
|
|
|
var fd protoreflect.FieldDescriptor
|
|
|
|
var xt protoreflect.ExtensionType
|
2019-09-15 00:17:39 -07:00
|
|
|
var xtErr error
|
2019-10-31 17:10:15 -07:00
|
|
|
var isFieldNumberName bool
|
|
|
|
|
|
|
|
switch tok.NameKind() {
|
|
|
|
case text.IdentName:
|
2022-05-24 05:12:23 +09:00
|
|
|
name = protoreflect.Name(tok.IdentName())
|
2020-06-24 16:47:32 -07:00
|
|
|
fd = fieldDescs.ByTextName(string(name))
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
case text.TypeName:
|
2019-01-04 14:08:41 -08:00
|
|
|
// Handle extensions only. This code path is not for Any.
|
2022-05-24 05:12:23 +09:00
|
|
|
xt, xtErr = d.opts.Resolver.FindExtensionByName(protoreflect.FullName(tok.TypeName()))
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
case text.FieldNumber:
|
|
|
|
isFieldNumberName = true
|
2022-05-24 05:12:23 +09:00
|
|
|
num := protoreflect.FieldNumber(tok.FieldNumber())
|
2019-09-15 00:17:39 -07:00
|
|
|
if !num.IsValid() {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "invalid field number: %d", num)
|
2019-05-01 12:29:25 -07:00
|
|
|
}
|
2019-09-15 00:17:39 -07:00
|
|
|
fd = fieldDescs.ByNumber(num)
|
|
|
|
if fd == nil {
|
2019-10-31 17:10:15 -07:00
|
|
|
xt, xtErr = d.opts.Resolver.FindExtensionByNumber(messageDesc.FullName(), num)
|
2019-08-02 16:58:08 -07:00
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2019-09-15 00:17:39 -07:00
|
|
|
if xt != nil {
|
|
|
|
fd = xt.TypeDescriptor()
|
|
|
|
if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName())
|
2019-09-15 00:17:39 -07:00
|
|
|
}
|
|
|
|
} else if xtErr != nil && xtErr != protoregistry.NotFound {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr)
|
2019-09-15 00:17:39 -07:00
|
|
|
}
|
2019-08-10 13:56:36 -07:00
|
|
|
if flags.ProtoLegacy {
|
|
|
|
if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
|
|
|
|
fd = nil // reset since the weak reference is not linked in
|
|
|
|
}
|
2019-09-15 00:17:39 -07:00
|
|
|
}
|
2018-12-18 18:04:31 -08:00
|
|
|
|
2019-09-15 00:17:39 -07:00
|
|
|
// Handle unknown fields.
|
2018-12-06 15:28:53 -08:00
|
|
|
if fd == nil {
|
2019-10-31 17:10:15 -07:00
|
|
|
if d.opts.DiscardUnknown || messageDesc.ReservedNames().Has(name) {
|
|
|
|
d.skipValue()
|
2018-12-13 14:41:22 -08:00
|
|
|
continue
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "unknown field: %v", tok.RawString())
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-09-15 00:17:39 -07:00
|
|
|
// Handle fields identified by field number.
|
2019-10-31 17:10:15 -07:00
|
|
|
if isFieldNumberName {
|
2019-09-15 00:17:39 -07:00
|
|
|
// TODO: Add an option to permit parsing field numbers.
|
|
|
|
//
|
|
|
|
// This requires careful thought as the MarshalOptions.EmitUnknown
|
2019-10-31 17:10:15 -07:00
|
|
|
// option allows formatting unknown fields as the field number and the
|
|
|
|
// best-effort textual representation of the field value. In that case,
|
|
|
|
// it may not be possible to unmarshal the value from a parser that does
|
|
|
|
// have information about the unknown field.
|
|
|
|
return d.newError(tok.Pos(), "cannot specify field by number: %v", tok.RawString())
|
2019-09-15 00:17:39 -07:00
|
|
|
}
|
|
|
|
|
2019-05-13 14:32:56 -07:00
|
|
|
switch {
|
|
|
|
case fd.IsList():
|
2019-10-31 17:10:15 -07:00
|
|
|
kind := fd.Kind()
|
2022-05-24 05:12:23 +09:00
|
|
|
if kind != protoreflect.MessageKind && kind != protoreflect.GroupKind && !tok.HasSeparator() {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.syntaxError(tok.Pos(), "missing field separator :")
|
2019-05-13 14:32:56 -07:00
|
|
|
}
|
|
|
|
|
2019-04-25 23:48:08 -07:00
|
|
|
list := m.Mutable(fd).List()
|
2019-10-31 17:10:15 -07:00
|
|
|
if err := d.unmarshalList(fd, list); err != nil {
|
2019-05-13 14:32:56 -07:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
case fd.IsMap():
|
2019-04-25 23:48:08 -07:00
|
|
|
mmap := m.Mutable(fd).Map()
|
2019-10-31 17:10:15 -07:00
|
|
|
if err := d.unmarshalMap(fd, mmap); err != nil {
|
2018-12-06 15:28:53 -08:00
|
|
|
return err
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2019-05-13 14:32:56 -07:00
|
|
|
default:
|
2019-10-31 17:10:15 -07:00
|
|
|
kind := fd.Kind()
|
2022-05-24 05:12:23 +09:00
|
|
|
if kind != protoreflect.MessageKind && kind != protoreflect.GroupKind && !tok.HasSeparator() {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.syntaxError(tok.Pos(), "missing field separator :")
|
|
|
|
}
|
|
|
|
|
2019-04-02 20:19:36 -07:00
|
|
|
// If field is a oneof, check if it has already been set.
|
2019-05-13 14:32:56 -07:00
|
|
|
if od := fd.ContainingOneof(); od != nil {
|
2019-04-02 20:19:36 -07:00
|
|
|
idx := uint64(od.Index())
|
|
|
|
if seenOneofs.Has(idx) {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "error parsing %q, oneof %v is already set", tok.RawString(), od.FullName())
|
2019-04-02 20:19:36 -07:00
|
|
|
}
|
|
|
|
seenOneofs.Set(idx)
|
|
|
|
}
|
|
|
|
|
2018-12-06 15:28:53 -08:00
|
|
|
num := uint64(fd.Number())
|
|
|
|
if seenNums.Has(num) {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "non-repeated field %q is repeated", tok.RawString())
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
if err := d.unmarshalSingular(fd, m); err != nil {
|
2018-12-06 15:28:53 -08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
seenNums.Set(num)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-19 09:28:29 -07:00
|
|
|
return nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
// unmarshalSingular unmarshals a non-repeated field value specified by the
|
|
|
|
// given FieldDescriptor.
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d decoder) unmarshalSingular(fd protoreflect.FieldDescriptor, m protoreflect.Message) error {
|
|
|
|
var val protoreflect.Value
|
2019-10-31 17:10:15 -07:00
|
|
|
var err error
|
2018-12-06 15:28:53 -08:00
|
|
|
switch fd.Kind() {
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
2019-09-04 10:46:00 -07:00
|
|
|
val = m.NewField(fd)
|
2019-10-31 17:10:15 -07:00
|
|
|
err = d.unmarshalMessage(val.Message(), true)
|
2018-12-06 15:28:53 -08:00
|
|
|
default:
|
2019-10-31 17:10:15 -07:00
|
|
|
val, err = d.unmarshalScalar(fd)
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
if err == nil {
|
|
|
|
m.Set(fd, val)
|
|
|
|
}
|
|
|
|
return err
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
// unmarshalScalar unmarshals a scalar/enum protoreflect.Value specified by the
|
|
|
|
// given FieldDescriptor.
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
|
2019-10-31 17:10:15 -07:00
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.Value{}, err
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
if tok.Kind() != text.Scalar {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.Value{}, d.unexpectedTokenError(tok)
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
kind := fd.Kind()
|
|
|
|
switch kind {
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.BoolKind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if b, ok := tok.Bool(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfBool(b), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if n, ok := tok.Int32(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfInt32(n), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if n, ok := tok.Int64(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfInt64(n), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if n, ok := tok.Uint32(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfUint32(n), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if n, ok := tok.Uint64(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfUint64(n), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.FloatKind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if n, ok := tok.Float32(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfFloat32(n), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.DoubleKind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if n, ok := tok.Float64(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfFloat64(n), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.StringKind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if s, ok := tok.String(); ok {
|
encoding/prototext: adjust handling of invalid UTF-8
The following changes are made:
* Permit invalid UTF-8 in proto2. This goes against specified behavior,
but matches functional behavior in wire marshaling (not just for Go,
but also in the other major language implementations as well).
* The Format function is specified as ignoring errors since its intended
purpose is to surface information to the human user even if it's not
exactly parsible back into a message. As such, add an unexported
allowInvalidUTF8 option that is specially used by Format.
* Add an EmitASCII option that forces the formatting of
strings and bytes to always be encoded as ASCII.
This ensures that the entire output is always ASCII as well.
Note that we do not replicate this behavior for protojson since:
* The JSON format fundamentally has a stricter and well-specified
grammar for exactly what is valid/invalid, while the text format
has not had a well-specified grammar for the longest time,
leading to all sorts of weird usages due to Hyrum's law.
* This is to ease migration from the legacy implementation,
which did permit invalid UTF-8 in proto2.
* The EmitASCII option relies on the ability to always escape
Unicode characters using ASCII escape sequences, but this is not
possible in JSON since the grammar only has an escape sequence defined
for Unicode characters \u0000 to \uffff, inclusive.
However, Unicode v12.0.0 defines characters up to \U0010FFFF,
which is beyond what the JSON grammar provides escape sequences for.
Change-Id: I2b524a904e9ec59f9ed5500e299613bc27c31a14
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/233077
Reviewed-by: Herbie Ong <herbie@google.com>
2020-05-07 15:10:54 -07:00
|
|
|
if strs.EnforceUTF8(fd) && !utf8.ValidString(s) {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8")
|
2019-04-08 17:32:44 -07:00
|
|
|
}
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfString(s), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.BytesKind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if b, ok := tok.String(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfBytes([]byte(b)), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.EnumKind:
|
2019-10-31 17:10:15 -07:00
|
|
|
if lit, ok := tok.Enum(); ok {
|
2019-01-04 14:08:41 -08:00
|
|
|
// Lookup EnumNumber based on name.
|
2022-05-24 05:12:23 +09:00
|
|
|
if enumVal := fd.Enum().Values().ByName(protoreflect.Name(lit)); enumVal != nil {
|
|
|
|
return protoreflect.ValueOfEnum(enumVal.Number()), nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
if num, ok := tok.Int32(); ok {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.ValueOfEnum(protoreflect.EnumNumber(num)), nil
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
|
2018-12-06 15:28:53 -08:00
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("invalid scalar kind %v", kind))
|
|
|
|
}
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString())
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
// unmarshalList unmarshals into given protoreflect.List. A list value can
|
|
|
|
// either be in [] syntax or simply just a single scalar/message value.
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d decoder) unmarshalList(fd protoreflect.FieldDescriptor, list protoreflect.List) error {
|
2019-10-31 17:10:15 -07:00
|
|
|
tok, err := d.Peek()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-12-06 15:28:53 -08:00
|
|
|
switch fd.Kind() {
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
2019-10-31 17:10:15 -07:00
|
|
|
switch tok.Kind() {
|
|
|
|
case text.ListOpen:
|
|
|
|
d.Read()
|
|
|
|
for {
|
|
|
|
tok, err := d.Peek()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
switch tok.Kind() {
|
|
|
|
case text.ListClose:
|
|
|
|
d.Read()
|
|
|
|
return nil
|
|
|
|
case text.MessageOpen:
|
|
|
|
pval := list.NewElement()
|
|
|
|
if err := d.unmarshalMessage(pval.Message(), true); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
list.Append(pval)
|
|
|
|
default:
|
|
|
|
return d.unexpectedTokenError(tok)
|
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
case text.MessageOpen:
|
|
|
|
pval := list.NewElement()
|
|
|
|
if err := d.unmarshalMessage(pval.Message(), true); err != nil {
|
2018-12-06 15:28:53 -08:00
|
|
|
return err
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
list.Append(pval)
|
|
|
|
return nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2018-12-06 15:28:53 -08:00
|
|
|
default:
|
2019-10-31 17:10:15 -07:00
|
|
|
switch tok.Kind() {
|
|
|
|
case text.ListOpen:
|
|
|
|
d.Read()
|
|
|
|
for {
|
|
|
|
tok, err := d.Peek()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
switch tok.Kind() {
|
|
|
|
case text.ListClose:
|
|
|
|
d.Read()
|
|
|
|
return nil
|
|
|
|
case text.Scalar:
|
|
|
|
pval, err := d.unmarshalScalar(fd)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
list.Append(pval)
|
|
|
|
default:
|
|
|
|
return d.unexpectedTokenError(tok)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case text.Scalar:
|
|
|
|
pval, err := d.unmarshalScalar(fd)
|
2019-06-19 09:28:29 -07:00
|
|
|
if err != nil {
|
2018-12-06 15:28:53 -08:00
|
|
|
return err
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
list.Append(pval)
|
|
|
|
return nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.unexpectedTokenError(tok)
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
// unmarshalMap unmarshals into given protoreflect.Map. A map value is a
|
|
|
|
// textproto message containing {key: <kvalue>, value: <mvalue>}.
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d decoder) unmarshalMap(fd protoreflect.FieldDescriptor, mmap protoreflect.Map) error {
|
2019-10-31 17:10:15 -07:00
|
|
|
// Determine ahead whether map entry is a scalar type or a message type in
|
|
|
|
// order to call the appropriate unmarshalMapValue func inside
|
|
|
|
// unmarshalMapEntry.
|
2022-05-24 05:12:23 +09:00
|
|
|
var unmarshalMapValue func() (protoreflect.Value, error)
|
2019-05-13 14:32:56 -07:00
|
|
|
switch fd.MapValue().Kind() {
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
|
|
|
unmarshalMapValue = func() (protoreflect.Value, error) {
|
2019-10-31 17:10:15 -07:00
|
|
|
pval := mmap.NewValue()
|
|
|
|
if err := d.unmarshalMessage(pval.Message(), true); err != nil {
|
2022-05-24 05:12:23 +09:00
|
|
|
return protoreflect.Value{}, err
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
return pval, nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
default:
|
2022-05-24 05:12:23 +09:00
|
|
|
unmarshalMapValue = func() (protoreflect.Value, error) {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.unmarshalScalar(fd.MapValue())
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch tok.Kind() {
|
|
|
|
case text.MessageOpen:
|
|
|
|
return d.unmarshalMapEntry(fd, mmap, unmarshalMapValue)
|
2018-12-06 15:28:53 -08:00
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
case text.ListOpen:
|
|
|
|
for {
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch tok.Kind() {
|
|
|
|
case text.ListClose:
|
|
|
|
return nil
|
|
|
|
case text.MessageOpen:
|
|
|
|
if err := d.unmarshalMapEntry(fd, mmap, unmarshalMapValue); err != nil {
|
|
|
|
return err
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
default:
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.unexpectedTokenError(tok)
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
default:
|
|
|
|
return d.unexpectedTokenError(tok)
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
// unmarshalMap unmarshals into given protoreflect.Map. A map value is a
|
|
|
|
// textproto message containing {key: <kvalue>, value: <mvalue>}.
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d decoder) unmarshalMapEntry(fd protoreflect.FieldDescriptor, mmap protoreflect.Map, unmarshalMapValue func() (protoreflect.Value, error)) error {
|
|
|
|
var key protoreflect.MapKey
|
|
|
|
var pval protoreflect.Value
|
2019-10-31 17:10:15 -07:00
|
|
|
Loop:
|
|
|
|
for {
|
|
|
|
// Read field name.
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch tok.Kind() {
|
|
|
|
case text.Name:
|
|
|
|
if tok.NameKind() != text.IdentName {
|
|
|
|
if !d.opts.DiscardUnknown {
|
|
|
|
return d.newError(tok.Pos(), "unknown map entry field %q", tok.RawString())
|
|
|
|
}
|
|
|
|
d.skipValue()
|
|
|
|
continue Loop
|
|
|
|
}
|
|
|
|
// Continue below.
|
|
|
|
case text.MessageClose:
|
|
|
|
break Loop
|
|
|
|
default:
|
|
|
|
return d.unexpectedTokenError(tok)
|
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
switch name := protoreflect.Name(tok.IdentName()); name {
|
2020-05-26 11:21:59 -07:00
|
|
|
case genid.MapEntry_Key_field_name:
|
2019-10-31 17:10:15 -07:00
|
|
|
if !tok.HasSeparator() {
|
|
|
|
return d.syntaxError(tok.Pos(), "missing field separator :")
|
|
|
|
}
|
|
|
|
if key.IsValid() {
|
2020-05-26 11:21:59 -07:00
|
|
|
return d.newError(tok.Pos(), "map entry %q cannot be repeated", name)
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
val, err := d.unmarshalScalar(fd.MapKey())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
key = val.MapKey()
|
|
|
|
|
2020-05-26 11:21:59 -07:00
|
|
|
case genid.MapEntry_Value_field_name:
|
2022-05-24 05:12:23 +09:00
|
|
|
if kind := fd.MapValue().Kind(); (kind != protoreflect.MessageKind) && (kind != protoreflect.GroupKind) {
|
2019-10-31 17:10:15 -07:00
|
|
|
if !tok.HasSeparator() {
|
|
|
|
return d.syntaxError(tok.Pos(), "missing field separator :")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if pval.IsValid() {
|
2020-05-26 11:21:59 -07:00
|
|
|
return d.newError(tok.Pos(), "map entry %q cannot be repeated", name)
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
pval, err = unmarshalMapValue()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
if !d.opts.DiscardUnknown {
|
|
|
|
return d.newError(tok.Pos(), "unknown map entry field %q", name)
|
|
|
|
}
|
|
|
|
d.skipValue()
|
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
if !key.IsValid() {
|
|
|
|
key = fd.MapKey().Default().MapKey()
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
if !pval.IsValid() {
|
|
|
|
switch fd.MapValue().Kind() {
|
2022-05-24 05:12:23 +09:00
|
|
|
case protoreflect.MessageKind, protoreflect.GroupKind:
|
2019-10-31 17:10:15 -07:00
|
|
|
// If value field is not set for message/group types, construct an
|
|
|
|
// empty one as default.
|
|
|
|
pval = mmap.NewValue()
|
|
|
|
default:
|
|
|
|
pval = fd.MapValue().Default()
|
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
mmap.Set(key, pval)
|
2019-06-19 09:28:29 -07:00
|
|
|
return nil
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
// unmarshalAny unmarshals an Any textproto. It can either be in expanded form
|
|
|
|
// or non-expanded form.
|
2022-05-24 05:12:23 +09:00
|
|
|
func (d decoder) unmarshalAny(m protoreflect.Message, checkDelims bool) error {
|
2019-10-31 17:10:15 -07:00
|
|
|
var typeURL string
|
|
|
|
var bValue []byte
|
2020-05-27 14:47:34 -07:00
|
|
|
var seenTypeUrl bool
|
|
|
|
var seenValue bool
|
|
|
|
var isExpanded bool
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
if checkDelims {
|
|
|
|
tok, err := d.Read()
|
2019-06-19 09:28:29 -07:00
|
|
|
if err != nil {
|
2018-12-06 15:28:53 -08:00
|
|
|
return err
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
if tok.Kind() != text.MessageOpen {
|
|
|
|
return d.unexpectedTokenError(tok)
|
|
|
|
}
|
2018-12-06 15:28:53 -08:00
|
|
|
}
|
2019-01-04 14:08:41 -08:00
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
Loop:
|
|
|
|
for {
|
|
|
|
// Read field name. Can only have 3 possible field names, i.e. type_url,
|
|
|
|
// value and type URL name inside [].
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if typ := tok.Kind(); typ != text.Name {
|
|
|
|
if checkDelims {
|
|
|
|
if typ == text.MessageClose {
|
|
|
|
break Loop
|
|
|
|
}
|
|
|
|
} else if typ == text.EOF {
|
|
|
|
break Loop
|
|
|
|
}
|
|
|
|
return d.unexpectedTokenError(tok)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch tok.NameKind() {
|
|
|
|
case text.IdentName:
|
|
|
|
// Both type_url and value fields require field separator :.
|
|
|
|
if !tok.HasSeparator() {
|
|
|
|
return d.syntaxError(tok.Pos(), "missing field separator :")
|
|
|
|
}
|
|
|
|
|
2022-05-24 05:12:23 +09:00
|
|
|
switch name := protoreflect.Name(tok.IdentName()); name {
|
2020-05-26 11:21:59 -07:00
|
|
|
case genid.Any_TypeUrl_field_name:
|
2020-05-27 14:47:34 -07:00
|
|
|
if seenTypeUrl {
|
2020-05-26 11:21:59 -07:00
|
|
|
return d.newError(tok.Pos(), "duplicate %v field", genid.Any_TypeUrl_field_fullname)
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
2020-05-27 14:47:34 -07:00
|
|
|
if isExpanded {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "conflict with [%s] field", typeURL)
|
|
|
|
}
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
var ok bool
|
|
|
|
typeURL, ok = tok.String()
|
|
|
|
if !ok {
|
2020-05-26 11:21:59 -07:00
|
|
|
return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_TypeUrl_field_fullname, tok.RawString())
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
2020-05-27 14:47:34 -07:00
|
|
|
seenTypeUrl = true
|
2019-10-31 17:10:15 -07:00
|
|
|
|
2020-05-26 11:21:59 -07:00
|
|
|
case genid.Any_Value_field_name:
|
2020-05-27 14:47:34 -07:00
|
|
|
if seenValue {
|
2020-05-26 11:21:59 -07:00
|
|
|
return d.newError(tok.Pos(), "duplicate %v field", genid.Any_Value_field_fullname)
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
2020-05-27 14:47:34 -07:00
|
|
|
if isExpanded {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "conflict with [%s] field", typeURL)
|
|
|
|
}
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
s, ok := tok.String()
|
|
|
|
if !ok {
|
2020-05-26 11:21:59 -07:00
|
|
|
return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_Value_field_fullname, tok.RawString())
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
bValue = []byte(s)
|
2020-05-27 14:47:34 -07:00
|
|
|
seenValue = true
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
default:
|
|
|
|
if !d.opts.DiscardUnknown {
|
2020-05-26 11:21:59 -07:00
|
|
|
return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname)
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
case text.TypeName:
|
2020-05-27 14:47:34 -07:00
|
|
|
if isExpanded {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "cannot have more than one type")
|
|
|
|
}
|
2020-05-27 14:47:34 -07:00
|
|
|
if seenTypeUrl {
|
2019-10-31 17:10:15 -07:00
|
|
|
return d.newError(tok.Pos(), "conflict with type_url field")
|
|
|
|
}
|
|
|
|
typeURL = tok.TypeName()
|
|
|
|
var err error
|
|
|
|
bValue, err = d.unmarshalExpandedAny(typeURL, tok.Pos())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-05-27 14:47:34 -07:00
|
|
|
isExpanded = true
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
default:
|
|
|
|
if !d.opts.DiscardUnknown {
|
2020-05-26 11:21:59 -07:00
|
|
|
return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname)
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
}
|
2019-01-04 14:08:41 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
fds := m.Descriptor().Fields()
|
|
|
|
if len(typeURL) > 0 {
|
2022-05-24 05:12:23 +09:00
|
|
|
m.Set(fds.ByNumber(genid.Any_TypeUrl_field_number), protoreflect.ValueOfString(typeURL))
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
if len(bValue) > 0 {
|
2022-05-24 05:12:23 +09:00
|
|
|
m.Set(fds.ByNumber(genid.Any_Value_field_number), protoreflect.ValueOfBytes(bValue))
|
2019-10-31 17:10:15 -07:00
|
|
|
}
|
|
|
|
return nil
|
2019-01-04 14:08:41 -08:00
|
|
|
}
|
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
func (d decoder) unmarshalExpandedAny(typeURL string, pos int) ([]byte, error) {
|
|
|
|
mt, err := d.opts.Resolver.FindMessageByURL(typeURL)
|
2019-06-19 09:28:29 -07:00
|
|
|
if err != nil {
|
2019-10-31 17:10:15 -07:00
|
|
|
return nil, d.newError(pos, "unable to resolve message [%v]: %v", typeURL, err)
|
2019-01-04 14:08:41 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
// Create new message for the embedded message type and unmarshal the value
|
|
|
|
// field into it.
|
|
|
|
m := mt.New()
|
|
|
|
if err := d.unmarshalMessage(m, true); err != nil {
|
|
|
|
return nil, err
|
2019-01-04 14:08:41 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
// Serialize the embedded message and return the resulting bytes.
|
2019-04-03 12:17:24 -07:00
|
|
|
b, err := proto.MarshalOptions{
|
2019-10-31 17:10:15 -07:00
|
|
|
AllowPartial: true, // Never check required fields inside an Any.
|
2019-04-03 12:17:24 -07:00
|
|
|
Deterministic: true,
|
2019-10-31 17:10:15 -07:00
|
|
|
}.Marshal(m.Interface())
|
2019-06-19 09:28:29 -07:00
|
|
|
if err != nil {
|
2019-10-31 17:10:15 -07:00
|
|
|
return nil, d.newError(pos, "error in marshaling message into Any.value: %v", err)
|
2019-01-04 14:08:41 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
return b, nil
|
|
|
|
}
|
2019-01-04 14:08:41 -08:00
|
|
|
|
2019-10-31 17:10:15 -07:00
|
|
|
// skipValue makes the decoder parse a field value in order to advance the read
|
|
|
|
// to the next field. It relies on Read returning an error if the types are not
|
|
|
|
// in valid sequence.
|
|
|
|
func (d decoder) skipValue() error {
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Only need to continue reading for messages and lists.
|
|
|
|
switch tok.Kind() {
|
|
|
|
case text.MessageOpen:
|
|
|
|
return d.skipMessageValue()
|
|
|
|
|
|
|
|
case text.ListOpen:
|
|
|
|
for {
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch tok.Kind() {
|
|
|
|
case text.ListClose:
|
|
|
|
return nil
|
|
|
|
case text.MessageOpen:
|
2023-09-26 14:56:57 -04:00
|
|
|
if err := d.skipMessageValue(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
default:
|
|
|
|
// Skip items. This will not validate whether skipped values are
|
|
|
|
// of the same type or not, same behavior as C++
|
|
|
|
// TextFormat::Parser::AllowUnknownField(true) version 3.8.0.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-19 09:28:29 -07:00
|
|
|
return nil
|
2019-01-04 14:08:41 -08:00
|
|
|
}
|
2019-10-31 17:10:15 -07:00
|
|
|
|
|
|
|
// skipMessageValue makes the decoder parse and skip over all fields in a
|
|
|
|
// message. It assumes that the previous read type is MessageOpen.
|
|
|
|
func (d decoder) skipMessageValue() error {
|
|
|
|
for {
|
|
|
|
tok, err := d.Read()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
switch tok.Kind() {
|
|
|
|
case text.MessageClose:
|
|
|
|
return nil
|
|
|
|
case text.Name:
|
|
|
|
if err := d.skipValue(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|