| 
									
										
										
										
											2021-08-12 21:03:24 +02: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. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package prototext | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"unicode/utf8" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/encoding/protowire" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/encoding/messageset" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/encoding/text" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/errors" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/flags" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/genid" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/order" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/pragma" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/strs" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/proto" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/reflect/protoreflect" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/reflect/protoregistry" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const defaultIndent = "  " | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Format formats the message as a multiline string. | 
					
						
							|  |  |  | // This function is only intended for human consumption and ignores errors. | 
					
						
							| 
									
										
										
										
											2024-05-06 08:50:47 +00:00
										 |  |  | // Do not depend on the output being stable. Its output will change across | 
					
						
							|  |  |  | // different builds of your program, even when using the same version of the | 
					
						
							|  |  |  | // protobuf module. | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | func Format(m proto.Message) string { | 
					
						
							|  |  |  | 	return MarshalOptions{Multiline: true}.Format(m) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 10:12:06 +00:00
										 |  |  | // Marshal writes the given [proto.Message] in textproto format using default | 
					
						
							| 
									
										
										
										
											2024-05-06 08:50:47 +00:00
										 |  |  | // options. Do not depend on the output being stable. Its output will change | 
					
						
							|  |  |  | // across different builds of your program, even when using the same version of | 
					
						
							|  |  |  | // the protobuf module. | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | func Marshal(m proto.Message) ([]byte, error) { | 
					
						
							|  |  |  | 	return MarshalOptions{}.Marshal(m) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MarshalOptions is a configurable text format marshaler. | 
					
						
							|  |  |  | type MarshalOptions struct { | 
					
						
							|  |  |  | 	pragma.NoUnkeyedLiterals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Multiline specifies whether the marshaler should format the output in | 
					
						
							|  |  |  | 	// indented-form with every textual element on a new line. | 
					
						
							|  |  |  | 	// If Indent is an empty string, then an arbitrary indent is chosen. | 
					
						
							|  |  |  | 	Multiline bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Indent specifies the set of indentation characters to use in a multiline | 
					
						
							|  |  |  | 	// formatted output such that every entry is preceded by Indent and | 
					
						
							|  |  |  | 	// terminated by a newline. If non-empty, then Multiline is treated as true. | 
					
						
							|  |  |  | 	// Indent can only be composed of space or tab characters. | 
					
						
							|  |  |  | 	Indent string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// EmitASCII specifies whether to format strings and bytes as ASCII only | 
					
						
							|  |  |  | 	// as opposed to using UTF-8 encoding when possible. | 
					
						
							|  |  |  | 	EmitASCII bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// allowInvalidUTF8 specifies whether to permit the encoding of strings | 
					
						
							|  |  |  | 	// with invalid UTF-8. This is unexported as it is intended to only | 
					
						
							|  |  |  | 	// be specified by the Format method. | 
					
						
							|  |  |  | 	allowInvalidUTF8 bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// AllowPartial allows messages that have missing required fields to marshal | 
					
						
							|  |  |  | 	// without returning an error. If AllowPartial is false (the default), | 
					
						
							|  |  |  | 	// Marshal will return error if there are any missing required fields. | 
					
						
							|  |  |  | 	AllowPartial bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// EmitUnknown specifies whether to emit unknown fields in the output. | 
					
						
							|  |  |  | 	// If specified, the unmarshaler may be unable to parse the output. | 
					
						
							|  |  |  | 	// The default is to exclude unknown fields. | 
					
						
							|  |  |  | 	EmitUnknown bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Resolver is used for looking up types when expanding google.protobuf.Any | 
					
						
							|  |  |  | 	// messages. If nil, this defaults to using protoregistry.GlobalTypes. | 
					
						
							|  |  |  | 	Resolver interface { | 
					
						
							|  |  |  | 		protoregistry.ExtensionTypeResolver | 
					
						
							|  |  |  | 		protoregistry.MessageTypeResolver | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Format formats the message as a string. | 
					
						
							|  |  |  | // This method is only intended for human consumption and ignores errors. | 
					
						
							| 
									
										
										
										
											2024-05-06 08:50:47 +00:00
										 |  |  | // Do not depend on the output being stable. Its output will change across | 
					
						
							|  |  |  | // different builds of your program, even when using the same version of the | 
					
						
							|  |  |  | // protobuf module. | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | func (o MarshalOptions) Format(m proto.Message) string { | 
					
						
							|  |  |  | 	if m == nil || !m.ProtoReflect().IsValid() { | 
					
						
							|  |  |  | 		return "<nil>" // invalid syntax, but okay since this is for debugging | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	o.allowInvalidUTF8 = true | 
					
						
							|  |  |  | 	o.AllowPartial = true | 
					
						
							|  |  |  | 	o.EmitUnknown = true | 
					
						
							|  |  |  | 	b, _ := o.Marshal(m) | 
					
						
							|  |  |  | 	return string(b) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-11 10:12:06 +00:00
										 |  |  | // Marshal writes the given [proto.Message] in textproto format using options in | 
					
						
							| 
									
										
										
										
											2024-05-06 08:50:47 +00:00
										 |  |  | // MarshalOptions object. Do not depend on the output being stable. Its output | 
					
						
							|  |  |  | // will change across different builds of your program, even when using the | 
					
						
							|  |  |  | // same version of the protobuf module. | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2023-07-10 12:58:06 +01:00
										 |  |  | 	return o.marshal(nil, m) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MarshalAppend appends the textproto format encoding of m to b, | 
					
						
							|  |  |  | // returning the result. | 
					
						
							|  |  |  | func (o MarshalOptions) MarshalAppend(b []byte, m proto.Message) ([]byte, error) { | 
					
						
							|  |  |  | 	return o.marshal(b, m) | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshal is a centralized function that all marshal operations go through. | 
					
						
							|  |  |  | // For profiling purposes, avoid changing the name of this function or | 
					
						
							|  |  |  | // introducing other code paths for marshal that do not go through this. | 
					
						
							| 
									
										
										
										
											2023-07-10 12:58:06 +01:00
										 |  |  | func (o MarshalOptions) marshal(b []byte, m proto.Message) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	var delims = [2]byte{'{', '}'} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if o.Multiline && o.Indent == "" { | 
					
						
							|  |  |  | 		o.Indent = defaultIndent | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if o.Resolver == nil { | 
					
						
							|  |  |  | 		o.Resolver = protoregistry.GlobalTypes | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-10 12:58:06 +01:00
										 |  |  | 	internalEnc, err := text.NewEncoder(b, o.Indent, delims, o.EmitASCII) | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Treat nil message interface as an empty message, | 
					
						
							|  |  |  | 	// in which case there is nothing to output. | 
					
						
							|  |  |  | 	if m == nil { | 
					
						
							| 
									
										
										
										
											2023-07-10 12:58:06 +01:00
										 |  |  | 		return b, nil | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	enc := encoder{internalEnc, o} | 
					
						
							|  |  |  | 	err = enc.marshalMessage(m.ProtoReflect(), false) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	out := enc.Bytes() | 
					
						
							|  |  |  | 	if len(o.Indent) > 0 && len(out) > 0 { | 
					
						
							|  |  |  | 		out = append(out, '\n') | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if o.AllowPartial { | 
					
						
							|  |  |  | 		return out, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return out, proto.CheckInitialized(m) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type encoder struct { | 
					
						
							|  |  |  | 	*text.Encoder | 
					
						
							|  |  |  | 	opts MarshalOptions | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshalMessage marshals the given protoreflect.Message. | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | func (e encoder) marshalMessage(m protoreflect.Message, inclDelims bool) error { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	messageDesc := m.Descriptor() | 
					
						
							|  |  |  | 	if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { | 
					
						
							|  |  |  | 		return errors.New("no support for proto1 MessageSets") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if inclDelims { | 
					
						
							|  |  |  | 		e.StartMessage() | 
					
						
							|  |  |  | 		defer e.EndMessage() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Handle Any expansion. | 
					
						
							|  |  |  | 	if messageDesc.FullName() == genid.Any_message_fullname { | 
					
						
							|  |  |  | 		if e.marshalAny(m) { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// If unable to expand, continue on to marshal Any as a regular message. | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Marshal fields. | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	order.RangeFields(m, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { | 
					
						
							|  |  |  | 		if err = e.marshalField(fd.TextName(), v, fd); err != nil { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Marshal unknown fields. | 
					
						
							|  |  |  | 	if e.opts.EmitUnknown { | 
					
						
							|  |  |  | 		e.marshalUnknown(m.GetUnknown()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshalField marshals the given field with protoreflect.Value. | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | func (e encoder) marshalField(name string, val protoreflect.Value, fd protoreflect.FieldDescriptor) error { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	switch { | 
					
						
							|  |  |  | 	case fd.IsList(): | 
					
						
							|  |  |  | 		return e.marshalList(name, val.List(), fd) | 
					
						
							|  |  |  | 	case fd.IsMap(): | 
					
						
							|  |  |  | 		return e.marshalMap(name, val.Map(), fd) | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		e.WriteName(name) | 
					
						
							|  |  |  | 		return e.marshalSingular(val, fd) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshalSingular marshals the given non-repeated field value. This includes | 
					
						
							|  |  |  | // all scalar types, enums, messages, and groups. | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | func (e encoder) marshalSingular(val protoreflect.Value, fd protoreflect.FieldDescriptor) error { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	kind := fd.Kind() | 
					
						
							|  |  |  | 	switch kind { | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.BoolKind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		e.WriteBool(val.Bool()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.StringKind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		s := val.String() | 
					
						
							|  |  |  | 		if !e.opts.allowInvalidUTF8 && strs.EnforceUTF8(fd) && !utf8.ValidString(s) { | 
					
						
							|  |  |  | 			return errors.InvalidUTF8(string(fd.FullName())) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		e.WriteString(s) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.Int32Kind, protoreflect.Int64Kind, | 
					
						
							|  |  |  | 		protoreflect.Sint32Kind, protoreflect.Sint64Kind, | 
					
						
							|  |  |  | 		protoreflect.Sfixed32Kind, protoreflect.Sfixed64Kind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		e.WriteInt(val.Int()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.Uint32Kind, protoreflect.Uint64Kind, | 
					
						
							|  |  |  | 		protoreflect.Fixed32Kind, protoreflect.Fixed64Kind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		e.WriteUint(val.Uint()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.FloatKind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		// Encoder.WriteFloat handles the special numbers NaN and infinites. | 
					
						
							|  |  |  | 		e.WriteFloat(val.Float(), 32) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.DoubleKind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		// Encoder.WriteFloat handles the special numbers NaN and infinites. | 
					
						
							|  |  |  | 		e.WriteFloat(val.Float(), 64) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.BytesKind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		e.WriteString(string(val.Bytes())) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.EnumKind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		num := val.Enum() | 
					
						
							|  |  |  | 		if desc := fd.Enum().Values().ByNumber(num); desc != nil { | 
					
						
							|  |  |  | 			e.WriteLiteral(string(desc.Name())) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			// Use numeric value if there is no enum description. | 
					
						
							|  |  |  | 			e.WriteInt(int64(num)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	case protoreflect.MessageKind, protoreflect.GroupKind: | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		return e.marshalMessage(val.Message(), true) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshalList marshals the given protoreflect.List as multiple name-value fields. | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | func (e encoder) marshalList(name string, list protoreflect.List, fd protoreflect.FieldDescriptor) error { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	size := list.Len() | 
					
						
							|  |  |  | 	for i := 0; i < size; i++ { | 
					
						
							|  |  |  | 		e.WriteName(name) | 
					
						
							|  |  |  | 		if err := e.marshalSingular(list.Get(i), fd); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshalMap marshals the given protoreflect.Map as multiple name-value fields. | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | func (e encoder) marshalMap(name string, mmap protoreflect.Map, fd protoreflect.FieldDescriptor) error { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	var err error | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | 	order.RangeEntries(mmap, order.GenericKeyOrder, func(key protoreflect.MapKey, val protoreflect.Value) bool { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		e.WriteName(name) | 
					
						
							|  |  |  | 		e.StartMessage() | 
					
						
							|  |  |  | 		defer e.EndMessage() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		e.WriteName(string(genid.MapEntry_Key_field_name)) | 
					
						
							|  |  |  | 		err = e.marshalSingular(key.Value(), fd.MapKey()) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		e.WriteName(string(genid.MapEntry_Value_field_name)) | 
					
						
							|  |  |  | 		err = e.marshalSingular(val, fd.MapValue()) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshalUnknown parses the given []byte and marshals fields out. | 
					
						
							|  |  |  | // This function assumes proper encoding in the given []byte. | 
					
						
							|  |  |  | func (e encoder) marshalUnknown(b []byte) { | 
					
						
							|  |  |  | 	const dec = 10 | 
					
						
							|  |  |  | 	const hex = 16 | 
					
						
							|  |  |  | 	for len(b) > 0 { | 
					
						
							|  |  |  | 		num, wtype, n := protowire.ConsumeTag(b) | 
					
						
							|  |  |  | 		b = b[n:] | 
					
						
							|  |  |  | 		e.WriteName(strconv.FormatInt(int64(num), dec)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch wtype { | 
					
						
							|  |  |  | 		case protowire.VarintType: | 
					
						
							|  |  |  | 			var v uint64 | 
					
						
							|  |  |  | 			v, n = protowire.ConsumeVarint(b) | 
					
						
							|  |  |  | 			e.WriteUint(v) | 
					
						
							|  |  |  | 		case protowire.Fixed32Type: | 
					
						
							|  |  |  | 			var v uint32 | 
					
						
							|  |  |  | 			v, n = protowire.ConsumeFixed32(b) | 
					
						
							|  |  |  | 			e.WriteLiteral("0x" + strconv.FormatUint(uint64(v), hex)) | 
					
						
							|  |  |  | 		case protowire.Fixed64Type: | 
					
						
							|  |  |  | 			var v uint64 | 
					
						
							|  |  |  | 			v, n = protowire.ConsumeFixed64(b) | 
					
						
							|  |  |  | 			e.WriteLiteral("0x" + strconv.FormatUint(v, hex)) | 
					
						
							|  |  |  | 		case protowire.BytesType: | 
					
						
							|  |  |  | 			var v []byte | 
					
						
							|  |  |  | 			v, n = protowire.ConsumeBytes(b) | 
					
						
							|  |  |  | 			e.WriteString(string(v)) | 
					
						
							|  |  |  | 		case protowire.StartGroupType: | 
					
						
							|  |  |  | 			e.StartMessage() | 
					
						
							|  |  |  | 			var v []byte | 
					
						
							|  |  |  | 			v, n = protowire.ConsumeGroup(num, b) | 
					
						
							|  |  |  | 			e.marshalUnknown(v) | 
					
						
							|  |  |  | 			e.EndMessage() | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			panic(fmt.Sprintf("prototext: error parsing unknown field wire type: %v", wtype)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		b = b[n:] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // marshalAny marshals the given google.protobuf.Any message in expanded form. | 
					
						
							|  |  |  | // It returns true if it was able to marshal, else false. | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | func (e encoder) marshalAny(any protoreflect.Message) bool { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	// Construct the embedded message. | 
					
						
							|  |  |  | 	fds := any.Descriptor().Fields() | 
					
						
							|  |  |  | 	fdType := fds.ByNumber(genid.Any_TypeUrl_field_number) | 
					
						
							|  |  |  | 	typeURL := any.Get(fdType).String() | 
					
						
							|  |  |  | 	mt, err := e.opts.Resolver.FindMessageByURL(typeURL) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	m := mt.New().Interface() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Unmarshal bytes into embedded message. | 
					
						
							|  |  |  | 	fdValue := fds.ByNumber(genid.Any_Value_field_number) | 
					
						
							|  |  |  | 	value := any.Get(fdValue) | 
					
						
							|  |  |  | 	err = proto.UnmarshalOptions{ | 
					
						
							|  |  |  | 		AllowPartial: true, | 
					
						
							|  |  |  | 		Resolver:     e.opts.Resolver, | 
					
						
							|  |  |  | 	}.Unmarshal(value.Bytes(), m) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Get current encoder position. If marshaling fails, reset encoder output | 
					
						
							|  |  |  | 	// back to this position. | 
					
						
							|  |  |  | 	pos := e.Snapshot() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Field name is the proto field name enclosed in []. | 
					
						
							|  |  |  | 	e.WriteName("[" + typeURL + "]") | 
					
						
							|  |  |  | 	err = e.marshalMessage(m.ProtoReflect(), true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		e.Reset(pos) | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true | 
					
						
							|  |  |  | } |