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 "strconv" 10*1c12ee1eSDan Willemsen "unicode/utf8" 11*1c12ee1eSDan Willemsen 12*1c12ee1eSDan Willemsen "google.golang.org/protobuf/encoding/protowire" 13*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/encoding/messageset" 14*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/encoding/text" 15*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/errors" 16*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/flags" 17*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/genid" 18*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/order" 19*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/pragma" 20*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/strs" 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 Willemsenconst defaultIndent = " " 27*1c12ee1eSDan Willemsen 28*1c12ee1eSDan Willemsen// Format formats the message as a multiline string. 29*1c12ee1eSDan Willemsen// This function is only intended for human consumption and ignores errors. 30*1c12ee1eSDan Willemsen// Do not depend on the output being stable. It may change over time across 31*1c12ee1eSDan Willemsen// different versions of the program. 32*1c12ee1eSDan Willemsenfunc Format(m proto.Message) string { 33*1c12ee1eSDan Willemsen return MarshalOptions{Multiline: true}.Format(m) 34*1c12ee1eSDan Willemsen} 35*1c12ee1eSDan Willemsen 36*1c12ee1eSDan Willemsen// Marshal writes the given proto.Message in textproto format using default 37*1c12ee1eSDan Willemsen// options. Do not depend on the output being stable. It may change over time 38*1c12ee1eSDan Willemsen// across different versions of the program. 39*1c12ee1eSDan Willemsenfunc Marshal(m proto.Message) ([]byte, error) { 40*1c12ee1eSDan Willemsen return MarshalOptions{}.Marshal(m) 41*1c12ee1eSDan Willemsen} 42*1c12ee1eSDan Willemsen 43*1c12ee1eSDan Willemsen// MarshalOptions is a configurable text format marshaler. 44*1c12ee1eSDan Willemsentype MarshalOptions struct { 45*1c12ee1eSDan Willemsen pragma.NoUnkeyedLiterals 46*1c12ee1eSDan Willemsen 47*1c12ee1eSDan Willemsen // Multiline specifies whether the marshaler should format the output in 48*1c12ee1eSDan Willemsen // indented-form with every textual element on a new line. 49*1c12ee1eSDan Willemsen // If Indent is an empty string, then an arbitrary indent is chosen. 50*1c12ee1eSDan Willemsen Multiline bool 51*1c12ee1eSDan Willemsen 52*1c12ee1eSDan Willemsen // Indent specifies the set of indentation characters to use in a multiline 53*1c12ee1eSDan Willemsen // formatted output such that every entry is preceded by Indent and 54*1c12ee1eSDan Willemsen // terminated by a newline. If non-empty, then Multiline is treated as true. 55*1c12ee1eSDan Willemsen // Indent can only be composed of space or tab characters. 56*1c12ee1eSDan Willemsen Indent string 57*1c12ee1eSDan Willemsen 58*1c12ee1eSDan Willemsen // EmitASCII specifies whether to format strings and bytes as ASCII only 59*1c12ee1eSDan Willemsen // as opposed to using UTF-8 encoding when possible. 60*1c12ee1eSDan Willemsen EmitASCII bool 61*1c12ee1eSDan Willemsen 62*1c12ee1eSDan Willemsen // allowInvalidUTF8 specifies whether to permit the encoding of strings 63*1c12ee1eSDan Willemsen // with invalid UTF-8. This is unexported as it is intended to only 64*1c12ee1eSDan Willemsen // be specified by the Format method. 65*1c12ee1eSDan Willemsen allowInvalidUTF8 bool 66*1c12ee1eSDan Willemsen 67*1c12ee1eSDan Willemsen // AllowPartial allows messages that have missing required fields to marshal 68*1c12ee1eSDan Willemsen // without returning an error. If AllowPartial is false (the default), 69*1c12ee1eSDan Willemsen // Marshal will return error if there are any missing required fields. 70*1c12ee1eSDan Willemsen AllowPartial bool 71*1c12ee1eSDan Willemsen 72*1c12ee1eSDan Willemsen // EmitUnknown specifies whether to emit unknown fields in the output. 73*1c12ee1eSDan Willemsen // If specified, the unmarshaler may be unable to parse the output. 74*1c12ee1eSDan Willemsen // The default is to exclude unknown fields. 75*1c12ee1eSDan Willemsen EmitUnknown bool 76*1c12ee1eSDan Willemsen 77*1c12ee1eSDan Willemsen // Resolver is used for looking up types when expanding google.protobuf.Any 78*1c12ee1eSDan Willemsen // messages. If nil, this defaults to using protoregistry.GlobalTypes. 79*1c12ee1eSDan Willemsen Resolver interface { 80*1c12ee1eSDan Willemsen protoregistry.ExtensionTypeResolver 81*1c12ee1eSDan Willemsen protoregistry.MessageTypeResolver 82*1c12ee1eSDan Willemsen } 83*1c12ee1eSDan Willemsen} 84*1c12ee1eSDan Willemsen 85*1c12ee1eSDan Willemsen// Format formats the message as a string. 86*1c12ee1eSDan Willemsen// This method is only intended for human consumption and ignores errors. 87*1c12ee1eSDan Willemsen// Do not depend on the output being stable. It may change over time across 88*1c12ee1eSDan Willemsen// different versions of the program. 89*1c12ee1eSDan Willemsenfunc (o MarshalOptions) Format(m proto.Message) string { 90*1c12ee1eSDan Willemsen if m == nil || !m.ProtoReflect().IsValid() { 91*1c12ee1eSDan Willemsen return "<nil>" // invalid syntax, but okay since this is for debugging 92*1c12ee1eSDan Willemsen } 93*1c12ee1eSDan Willemsen o.allowInvalidUTF8 = true 94*1c12ee1eSDan Willemsen o.AllowPartial = true 95*1c12ee1eSDan Willemsen o.EmitUnknown = true 96*1c12ee1eSDan Willemsen b, _ := o.Marshal(m) 97*1c12ee1eSDan Willemsen return string(b) 98*1c12ee1eSDan Willemsen} 99*1c12ee1eSDan Willemsen 100*1c12ee1eSDan Willemsen// Marshal writes the given proto.Message in textproto format using options in 101*1c12ee1eSDan Willemsen// MarshalOptions object. Do not depend on the output being stable. It may 102*1c12ee1eSDan Willemsen// change over time across different versions of the program. 103*1c12ee1eSDan Willemsenfunc (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { 104*1c12ee1eSDan Willemsen return o.marshal(m) 105*1c12ee1eSDan Willemsen} 106*1c12ee1eSDan Willemsen 107*1c12ee1eSDan Willemsen// marshal is a centralized function that all marshal operations go through. 108*1c12ee1eSDan Willemsen// For profiling purposes, avoid changing the name of this function or 109*1c12ee1eSDan Willemsen// introducing other code paths for marshal that do not go through this. 110*1c12ee1eSDan Willemsenfunc (o MarshalOptions) marshal(m proto.Message) ([]byte, error) { 111*1c12ee1eSDan Willemsen var delims = [2]byte{'{', '}'} 112*1c12ee1eSDan Willemsen 113*1c12ee1eSDan Willemsen if o.Multiline && o.Indent == "" { 114*1c12ee1eSDan Willemsen o.Indent = defaultIndent 115*1c12ee1eSDan Willemsen } 116*1c12ee1eSDan Willemsen if o.Resolver == nil { 117*1c12ee1eSDan Willemsen o.Resolver = protoregistry.GlobalTypes 118*1c12ee1eSDan Willemsen } 119*1c12ee1eSDan Willemsen 120*1c12ee1eSDan Willemsen internalEnc, err := text.NewEncoder(o.Indent, delims, o.EmitASCII) 121*1c12ee1eSDan Willemsen if err != nil { 122*1c12ee1eSDan Willemsen return nil, err 123*1c12ee1eSDan Willemsen } 124*1c12ee1eSDan Willemsen 125*1c12ee1eSDan Willemsen // Treat nil message interface as an empty message, 126*1c12ee1eSDan Willemsen // in which case there is nothing to output. 127*1c12ee1eSDan Willemsen if m == nil { 128*1c12ee1eSDan Willemsen return []byte{}, nil 129*1c12ee1eSDan Willemsen } 130*1c12ee1eSDan Willemsen 131*1c12ee1eSDan Willemsen enc := encoder{internalEnc, o} 132*1c12ee1eSDan Willemsen err = enc.marshalMessage(m.ProtoReflect(), false) 133*1c12ee1eSDan Willemsen if err != nil { 134*1c12ee1eSDan Willemsen return nil, err 135*1c12ee1eSDan Willemsen } 136*1c12ee1eSDan Willemsen out := enc.Bytes() 137*1c12ee1eSDan Willemsen if len(o.Indent) > 0 && len(out) > 0 { 138*1c12ee1eSDan Willemsen out = append(out, '\n') 139*1c12ee1eSDan Willemsen } 140*1c12ee1eSDan Willemsen if o.AllowPartial { 141*1c12ee1eSDan Willemsen return out, nil 142*1c12ee1eSDan Willemsen } 143*1c12ee1eSDan Willemsen return out, proto.CheckInitialized(m) 144*1c12ee1eSDan Willemsen} 145*1c12ee1eSDan Willemsen 146*1c12ee1eSDan Willemsentype encoder struct { 147*1c12ee1eSDan Willemsen *text.Encoder 148*1c12ee1eSDan Willemsen opts MarshalOptions 149*1c12ee1eSDan Willemsen} 150*1c12ee1eSDan Willemsen 151*1c12ee1eSDan Willemsen// marshalMessage marshals the given protoreflect.Message. 152*1c12ee1eSDan Willemsenfunc (e encoder) marshalMessage(m protoreflect.Message, inclDelims bool) error { 153*1c12ee1eSDan Willemsen messageDesc := m.Descriptor() 154*1c12ee1eSDan Willemsen if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { 155*1c12ee1eSDan Willemsen return errors.New("no support for proto1 MessageSets") 156*1c12ee1eSDan Willemsen } 157*1c12ee1eSDan Willemsen 158*1c12ee1eSDan Willemsen if inclDelims { 159*1c12ee1eSDan Willemsen e.StartMessage() 160*1c12ee1eSDan Willemsen defer e.EndMessage() 161*1c12ee1eSDan Willemsen } 162*1c12ee1eSDan Willemsen 163*1c12ee1eSDan Willemsen // Handle Any expansion. 164*1c12ee1eSDan Willemsen if messageDesc.FullName() == genid.Any_message_fullname { 165*1c12ee1eSDan Willemsen if e.marshalAny(m) { 166*1c12ee1eSDan Willemsen return nil 167*1c12ee1eSDan Willemsen } 168*1c12ee1eSDan Willemsen // If unable to expand, continue on to marshal Any as a regular message. 169*1c12ee1eSDan Willemsen } 170*1c12ee1eSDan Willemsen 171*1c12ee1eSDan Willemsen // Marshal fields. 172*1c12ee1eSDan Willemsen var err error 173*1c12ee1eSDan Willemsen order.RangeFields(m, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { 174*1c12ee1eSDan Willemsen if err = e.marshalField(fd.TextName(), v, fd); err != nil { 175*1c12ee1eSDan Willemsen return false 176*1c12ee1eSDan Willemsen } 177*1c12ee1eSDan Willemsen return true 178*1c12ee1eSDan Willemsen }) 179*1c12ee1eSDan Willemsen if err != nil { 180*1c12ee1eSDan Willemsen return err 181*1c12ee1eSDan Willemsen } 182*1c12ee1eSDan Willemsen 183*1c12ee1eSDan Willemsen // Marshal unknown fields. 184*1c12ee1eSDan Willemsen if e.opts.EmitUnknown { 185*1c12ee1eSDan Willemsen e.marshalUnknown(m.GetUnknown()) 186*1c12ee1eSDan Willemsen } 187*1c12ee1eSDan Willemsen 188*1c12ee1eSDan Willemsen return nil 189*1c12ee1eSDan Willemsen} 190*1c12ee1eSDan Willemsen 191*1c12ee1eSDan Willemsen// marshalField marshals the given field with protoreflect.Value. 192*1c12ee1eSDan Willemsenfunc (e encoder) marshalField(name string, val protoreflect.Value, fd protoreflect.FieldDescriptor) error { 193*1c12ee1eSDan Willemsen switch { 194*1c12ee1eSDan Willemsen case fd.IsList(): 195*1c12ee1eSDan Willemsen return e.marshalList(name, val.List(), fd) 196*1c12ee1eSDan Willemsen case fd.IsMap(): 197*1c12ee1eSDan Willemsen return e.marshalMap(name, val.Map(), fd) 198*1c12ee1eSDan Willemsen default: 199*1c12ee1eSDan Willemsen e.WriteName(name) 200*1c12ee1eSDan Willemsen return e.marshalSingular(val, fd) 201*1c12ee1eSDan Willemsen } 202*1c12ee1eSDan Willemsen} 203*1c12ee1eSDan Willemsen 204*1c12ee1eSDan Willemsen// marshalSingular marshals the given non-repeated field value. This includes 205*1c12ee1eSDan Willemsen// all scalar types, enums, messages, and groups. 206*1c12ee1eSDan Willemsenfunc (e encoder) marshalSingular(val protoreflect.Value, fd protoreflect.FieldDescriptor) error { 207*1c12ee1eSDan Willemsen kind := fd.Kind() 208*1c12ee1eSDan Willemsen switch kind { 209*1c12ee1eSDan Willemsen case protoreflect.BoolKind: 210*1c12ee1eSDan Willemsen e.WriteBool(val.Bool()) 211*1c12ee1eSDan Willemsen 212*1c12ee1eSDan Willemsen case protoreflect.StringKind: 213*1c12ee1eSDan Willemsen s := val.String() 214*1c12ee1eSDan Willemsen if !e.opts.allowInvalidUTF8 && strs.EnforceUTF8(fd) && !utf8.ValidString(s) { 215*1c12ee1eSDan Willemsen return errors.InvalidUTF8(string(fd.FullName())) 216*1c12ee1eSDan Willemsen } 217*1c12ee1eSDan Willemsen e.WriteString(s) 218*1c12ee1eSDan Willemsen 219*1c12ee1eSDan Willemsen case protoreflect.Int32Kind, protoreflect.Int64Kind, 220*1c12ee1eSDan Willemsen protoreflect.Sint32Kind, protoreflect.Sint64Kind, 221*1c12ee1eSDan Willemsen protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: 222*1c12ee1eSDan Willemsen e.WriteInt(val.Int()) 223*1c12ee1eSDan Willemsen 224*1c12ee1eSDan Willemsen case protoreflect.Uint32Kind, protoreflect.Uint64Kind, 225*1c12ee1eSDan Willemsen protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: 226*1c12ee1eSDan Willemsen e.WriteUint(val.Uint()) 227*1c12ee1eSDan Willemsen 228*1c12ee1eSDan Willemsen case protoreflect.FloatKind: 229*1c12ee1eSDan Willemsen // Encoder.WriteFloat handles the special numbers NaN and infinites. 230*1c12ee1eSDan Willemsen e.WriteFloat(val.Float(), 32) 231*1c12ee1eSDan Willemsen 232*1c12ee1eSDan Willemsen case protoreflect.DoubleKind: 233*1c12ee1eSDan Willemsen // Encoder.WriteFloat handles the special numbers NaN and infinites. 234*1c12ee1eSDan Willemsen e.WriteFloat(val.Float(), 64) 235*1c12ee1eSDan Willemsen 236*1c12ee1eSDan Willemsen case protoreflect.BytesKind: 237*1c12ee1eSDan Willemsen e.WriteString(string(val.Bytes())) 238*1c12ee1eSDan Willemsen 239*1c12ee1eSDan Willemsen case protoreflect.EnumKind: 240*1c12ee1eSDan Willemsen num := val.Enum() 241*1c12ee1eSDan Willemsen if desc := fd.Enum().Values().ByNumber(num); desc != nil { 242*1c12ee1eSDan Willemsen e.WriteLiteral(string(desc.Name())) 243*1c12ee1eSDan Willemsen } else { 244*1c12ee1eSDan Willemsen // Use numeric value if there is no enum description. 245*1c12ee1eSDan Willemsen e.WriteInt(int64(num)) 246*1c12ee1eSDan Willemsen } 247*1c12ee1eSDan Willemsen 248*1c12ee1eSDan Willemsen case protoreflect.MessageKind, protoreflect.GroupKind: 249*1c12ee1eSDan Willemsen return e.marshalMessage(val.Message(), true) 250*1c12ee1eSDan Willemsen 251*1c12ee1eSDan Willemsen default: 252*1c12ee1eSDan Willemsen panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind)) 253*1c12ee1eSDan Willemsen } 254*1c12ee1eSDan Willemsen return nil 255*1c12ee1eSDan Willemsen} 256*1c12ee1eSDan Willemsen 257*1c12ee1eSDan Willemsen// marshalList marshals the given protoreflect.List as multiple name-value fields. 258*1c12ee1eSDan Willemsenfunc (e encoder) marshalList(name string, list protoreflect.List, fd protoreflect.FieldDescriptor) error { 259*1c12ee1eSDan Willemsen size := list.Len() 260*1c12ee1eSDan Willemsen for i := 0; i < size; i++ { 261*1c12ee1eSDan Willemsen e.WriteName(name) 262*1c12ee1eSDan Willemsen if err := e.marshalSingular(list.Get(i), fd); err != nil { 263*1c12ee1eSDan Willemsen return err 264*1c12ee1eSDan Willemsen } 265*1c12ee1eSDan Willemsen } 266*1c12ee1eSDan Willemsen return nil 267*1c12ee1eSDan Willemsen} 268*1c12ee1eSDan Willemsen 269*1c12ee1eSDan Willemsen// marshalMap marshals the given protoreflect.Map as multiple name-value fields. 270*1c12ee1eSDan Willemsenfunc (e encoder) marshalMap(name string, mmap protoreflect.Map, fd protoreflect.FieldDescriptor) error { 271*1c12ee1eSDan Willemsen var err error 272*1c12ee1eSDan Willemsen order.RangeEntries(mmap, order.GenericKeyOrder, func(key protoreflect.MapKey, val protoreflect.Value) bool { 273*1c12ee1eSDan Willemsen e.WriteName(name) 274*1c12ee1eSDan Willemsen e.StartMessage() 275*1c12ee1eSDan Willemsen defer e.EndMessage() 276*1c12ee1eSDan Willemsen 277*1c12ee1eSDan Willemsen e.WriteName(string(genid.MapEntry_Key_field_name)) 278*1c12ee1eSDan Willemsen err = e.marshalSingular(key.Value(), fd.MapKey()) 279*1c12ee1eSDan Willemsen if err != nil { 280*1c12ee1eSDan Willemsen return false 281*1c12ee1eSDan Willemsen } 282*1c12ee1eSDan Willemsen 283*1c12ee1eSDan Willemsen e.WriteName(string(genid.MapEntry_Value_field_name)) 284*1c12ee1eSDan Willemsen err = e.marshalSingular(val, fd.MapValue()) 285*1c12ee1eSDan Willemsen if err != nil { 286*1c12ee1eSDan Willemsen return false 287*1c12ee1eSDan Willemsen } 288*1c12ee1eSDan Willemsen return true 289*1c12ee1eSDan Willemsen }) 290*1c12ee1eSDan Willemsen return err 291*1c12ee1eSDan Willemsen} 292*1c12ee1eSDan Willemsen 293*1c12ee1eSDan Willemsen// marshalUnknown parses the given []byte and marshals fields out. 294*1c12ee1eSDan Willemsen// This function assumes proper encoding in the given []byte. 295*1c12ee1eSDan Willemsenfunc (e encoder) marshalUnknown(b []byte) { 296*1c12ee1eSDan Willemsen const dec = 10 297*1c12ee1eSDan Willemsen const hex = 16 298*1c12ee1eSDan Willemsen for len(b) > 0 { 299*1c12ee1eSDan Willemsen num, wtype, n := protowire.ConsumeTag(b) 300*1c12ee1eSDan Willemsen b = b[n:] 301*1c12ee1eSDan Willemsen e.WriteName(strconv.FormatInt(int64(num), dec)) 302*1c12ee1eSDan Willemsen 303*1c12ee1eSDan Willemsen switch wtype { 304*1c12ee1eSDan Willemsen case protowire.VarintType: 305*1c12ee1eSDan Willemsen var v uint64 306*1c12ee1eSDan Willemsen v, n = protowire.ConsumeVarint(b) 307*1c12ee1eSDan Willemsen e.WriteUint(v) 308*1c12ee1eSDan Willemsen case protowire.Fixed32Type: 309*1c12ee1eSDan Willemsen var v uint32 310*1c12ee1eSDan Willemsen v, n = protowire.ConsumeFixed32(b) 311*1c12ee1eSDan Willemsen e.WriteLiteral("0x" + strconv.FormatUint(uint64(v), hex)) 312*1c12ee1eSDan Willemsen case protowire.Fixed64Type: 313*1c12ee1eSDan Willemsen var v uint64 314*1c12ee1eSDan Willemsen v, n = protowire.ConsumeFixed64(b) 315*1c12ee1eSDan Willemsen e.WriteLiteral("0x" + strconv.FormatUint(v, hex)) 316*1c12ee1eSDan Willemsen case protowire.BytesType: 317*1c12ee1eSDan Willemsen var v []byte 318*1c12ee1eSDan Willemsen v, n = protowire.ConsumeBytes(b) 319*1c12ee1eSDan Willemsen e.WriteString(string(v)) 320*1c12ee1eSDan Willemsen case protowire.StartGroupType: 321*1c12ee1eSDan Willemsen e.StartMessage() 322*1c12ee1eSDan Willemsen var v []byte 323*1c12ee1eSDan Willemsen v, n = protowire.ConsumeGroup(num, b) 324*1c12ee1eSDan Willemsen e.marshalUnknown(v) 325*1c12ee1eSDan Willemsen e.EndMessage() 326*1c12ee1eSDan Willemsen default: 327*1c12ee1eSDan Willemsen panic(fmt.Sprintf("prototext: error parsing unknown field wire type: %v", wtype)) 328*1c12ee1eSDan Willemsen } 329*1c12ee1eSDan Willemsen 330*1c12ee1eSDan Willemsen b = b[n:] 331*1c12ee1eSDan Willemsen } 332*1c12ee1eSDan Willemsen} 333*1c12ee1eSDan Willemsen 334*1c12ee1eSDan Willemsen// marshalAny marshals the given google.protobuf.Any message in expanded form. 335*1c12ee1eSDan Willemsen// It returns true if it was able to marshal, else false. 336*1c12ee1eSDan Willemsenfunc (e encoder) marshalAny(any protoreflect.Message) bool { 337*1c12ee1eSDan Willemsen // Construct the embedded message. 338*1c12ee1eSDan Willemsen fds := any.Descriptor().Fields() 339*1c12ee1eSDan Willemsen fdType := fds.ByNumber(genid.Any_TypeUrl_field_number) 340*1c12ee1eSDan Willemsen typeURL := any.Get(fdType).String() 341*1c12ee1eSDan Willemsen mt, err := e.opts.Resolver.FindMessageByURL(typeURL) 342*1c12ee1eSDan Willemsen if err != nil { 343*1c12ee1eSDan Willemsen return false 344*1c12ee1eSDan Willemsen } 345*1c12ee1eSDan Willemsen m := mt.New().Interface() 346*1c12ee1eSDan Willemsen 347*1c12ee1eSDan Willemsen // Unmarshal bytes into embedded message. 348*1c12ee1eSDan Willemsen fdValue := fds.ByNumber(genid.Any_Value_field_number) 349*1c12ee1eSDan Willemsen value := any.Get(fdValue) 350*1c12ee1eSDan Willemsen err = proto.UnmarshalOptions{ 351*1c12ee1eSDan Willemsen AllowPartial: true, 352*1c12ee1eSDan Willemsen Resolver: e.opts.Resolver, 353*1c12ee1eSDan Willemsen }.Unmarshal(value.Bytes(), m) 354*1c12ee1eSDan Willemsen if err != nil { 355*1c12ee1eSDan Willemsen return false 356*1c12ee1eSDan Willemsen } 357*1c12ee1eSDan Willemsen 358*1c12ee1eSDan Willemsen // Get current encoder position. If marshaling fails, reset encoder output 359*1c12ee1eSDan Willemsen // back to this position. 360*1c12ee1eSDan Willemsen pos := e.Snapshot() 361*1c12ee1eSDan Willemsen 362*1c12ee1eSDan Willemsen // Field name is the proto field name enclosed in []. 363*1c12ee1eSDan Willemsen e.WriteName("[" + typeURL + "]") 364*1c12ee1eSDan Willemsen err = e.marshalMessage(m.ProtoReflect(), true) 365*1c12ee1eSDan Willemsen if err != nil { 366*1c12ee1eSDan Willemsen e.Reset(pos) 367*1c12ee1eSDan Willemsen return false 368*1c12ee1eSDan Willemsen } 369*1c12ee1eSDan Willemsen return true 370*1c12ee1eSDan Willemsen} 371