| 
									
										
										
										
											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 proto | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/encoding/protowire" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/encoding/messageset" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/errors" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/genid" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/internal/pragma" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/reflect/protoreflect" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/reflect/protoregistry" | 
					
						
							|  |  |  | 	"google.golang.org/protobuf/runtime/protoiface" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // UnmarshalOptions configures the unmarshaler. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Example usage: | 
					
						
							| 
									
										
										
										
											2022-09-28 18:30:40 +01:00
										 |  |  | // | 
					
						
							|  |  |  | //	err := UnmarshalOptions{DiscardUnknown: true}.Unmarshal(b, m) | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | type UnmarshalOptions struct { | 
					
						
							|  |  |  | 	pragma.NoUnkeyedLiterals | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Merge merges the input into the destination message. | 
					
						
							|  |  |  | 	// The default behavior is to always reset the message before unmarshaling, | 
					
						
							|  |  |  | 	// unless Merge is specified. | 
					
						
							|  |  |  | 	Merge bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// AllowPartial accepts input for messages that will result in missing | 
					
						
							|  |  |  | 	// required fields. If AllowPartial is false (the default), Unmarshal will | 
					
						
							|  |  |  | 	// return an error if there are any missing required fields. | 
					
						
							|  |  |  | 	AllowPartial bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If DiscardUnknown is set, unknown fields are ignored. | 
					
						
							|  |  |  | 	DiscardUnknown bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Resolver is used for looking up types when unmarshaling extension fields. | 
					
						
							|  |  |  | 	// If nil, this defaults to using protoregistry.GlobalTypes. | 
					
						
							|  |  |  | 	Resolver interface { | 
					
						
							|  |  |  | 		FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) | 
					
						
							|  |  |  | 		FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-05-02 14:05:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// RecursionLimit limits how deeply messages may be nested. | 
					
						
							|  |  |  | 	// If zero, a default limit is applied. | 
					
						
							|  |  |  | 	RecursionLimit int | 
					
						
							| 
									
										
										
										
											2025-01-14 13:10:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// | 
					
						
							|  |  |  | 	// NoLazyDecoding turns off lazy decoding, which otherwise is enabled by | 
					
						
							|  |  |  | 	// default. Lazy decoding only affects submessages (annotated with [lazy = | 
					
						
							|  |  |  | 	// true] in the .proto file) within messages that use the Opaque API. | 
					
						
							|  |  |  | 	NoLazyDecoding bool | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Unmarshal parses the wire-format message in b and places the result in m. | 
					
						
							|  |  |  | // The provided message must be mutable (e.g., a non-nil pointer to a message). | 
					
						
							| 
									
										
										
										
											2024-05-06 08:50:47 +00:00
										 |  |  | // | 
					
						
							|  |  |  | // See the [UnmarshalOptions] type if you need more control. | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | func Unmarshal(b []byte, m Message) error { | 
					
						
							| 
									
										
										
										
											2022-05-02 14:05:18 +01:00
										 |  |  | 	_, err := UnmarshalOptions{RecursionLimit: protowire.DefaultRecursionLimit}.unmarshal(b, m.ProtoReflect()) | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Unmarshal parses the wire-format message in b and places the result in m. | 
					
						
							|  |  |  | // The provided message must be mutable (e.g., a non-nil pointer to a message). | 
					
						
							|  |  |  | func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error { | 
					
						
							| 
									
										
										
										
											2022-05-02 14:05:18 +01:00
										 |  |  | 	if o.RecursionLimit == 0 { | 
					
						
							|  |  |  | 		o.RecursionLimit = protowire.DefaultRecursionLimit | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	_, err := o.unmarshal(b, m.ProtoReflect()) | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // UnmarshalState parses a wire-format message and places the result in m. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This method permits fine-grained control over the unmarshaler. | 
					
						
							| 
									
										
										
										
											2024-03-11 10:12:06 +00:00
										 |  |  | // Most users should use [Unmarshal] instead. | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { | 
					
						
							| 
									
										
										
										
											2022-05-02 14:05:18 +01:00
										 |  |  | 	if o.RecursionLimit == 0 { | 
					
						
							|  |  |  | 		o.RecursionLimit = protowire.DefaultRecursionLimit | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 	return o.unmarshal(in.Buf, in.Message) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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 protoreflect.Message) (out protoiface.UnmarshalOutput, err error) { | 
					
						
							|  |  |  | 	if o.Resolver == nil { | 
					
						
							|  |  |  | 		o.Resolver = protoregistry.GlobalTypes | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !o.Merge { | 
					
						
							|  |  |  | 		Reset(m.Interface()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	allowPartial := o.AllowPartial | 
					
						
							|  |  |  | 	o.Merge = true | 
					
						
							|  |  |  | 	o.AllowPartial = true | 
					
						
							|  |  |  | 	methods := protoMethods(m) | 
					
						
							|  |  |  | 	if methods != nil && methods.Unmarshal != nil && | 
					
						
							|  |  |  | 		!(o.DiscardUnknown && methods.Flags&protoiface.SupportUnmarshalDiscardUnknown == 0) { | 
					
						
							|  |  |  | 		in := protoiface.UnmarshalInput{ | 
					
						
							|  |  |  | 			Message:  m, | 
					
						
							|  |  |  | 			Buf:      b, | 
					
						
							|  |  |  | 			Resolver: o.Resolver, | 
					
						
							| 
									
										
										
										
											2022-05-02 14:05:18 +01:00
										 |  |  | 			Depth:    o.RecursionLimit, | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if o.DiscardUnknown { | 
					
						
							|  |  |  | 			in.Flags |= protoiface.UnmarshalDiscardUnknown | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-01-14 13:10:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if !allowPartial { | 
					
						
							|  |  |  | 			// This does not affect how current unmarshal functions work, it just allows them | 
					
						
							|  |  |  | 			// to record this for lazy the decoding case. | 
					
						
							|  |  |  | 			in.Flags |= protoiface.UnmarshalCheckRequired | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if o.NoLazyDecoding { | 
					
						
							|  |  |  | 			in.Flags |= protoiface.UnmarshalNoLazyDecoding | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		out, err = methods.Unmarshal(in) | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2022-05-02 14:05:18 +01:00
										 |  |  | 		o.RecursionLimit-- | 
					
						
							|  |  |  | 		if o.RecursionLimit < 0 { | 
					
						
							|  |  |  | 			return out, errors.New("exceeded max recursion depth") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		err = o.unmarshalMessageSlow(b, m) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return out, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if allowPartial || (out.Flags&protoiface.UnmarshalInitialized != 0) { | 
					
						
							|  |  |  | 		return out, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return out, checkInitialized(m) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) error { | 
					
						
							|  |  |  | 	_, err := o.unmarshal(b, m) | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message) error { | 
					
						
							|  |  |  | 	md := m.Descriptor() | 
					
						
							|  |  |  | 	if messageset.IsMessageSet(md) { | 
					
						
							|  |  |  | 		return o.unmarshalMessageSet(b, m) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	fields := md.Fields() | 
					
						
							|  |  |  | 	for len(b) > 0 { | 
					
						
							|  |  |  | 		// Parse the tag (field number and wire type). | 
					
						
							|  |  |  | 		num, wtyp, tagLen := protowire.ConsumeTag(b) | 
					
						
							|  |  |  | 		if tagLen < 0 { | 
					
						
							|  |  |  | 			return errDecode | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if num > protowire.MaxValidNumber { | 
					
						
							|  |  |  | 			return errDecode | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Find the field descriptor for this field number. | 
					
						
							|  |  |  | 		fd := fields.ByNumber(num) | 
					
						
							|  |  |  | 		if fd == nil && md.ExtensionRanges().Has(num) { | 
					
						
							|  |  |  | 			extType, err := o.Resolver.FindExtensionByNumber(md.FullName(), num) | 
					
						
							|  |  |  | 			if err != nil && err != protoregistry.NotFound { | 
					
						
							|  |  |  | 				return errors.New("%v: unable to resolve extension %v: %v", md.FullName(), num, err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if extType != nil { | 
					
						
							|  |  |  | 				fd = extType.TypeDescriptor() | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		var err error | 
					
						
							|  |  |  | 		if fd == nil { | 
					
						
							|  |  |  | 			err = errUnknown | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Parse the field value. | 
					
						
							|  |  |  | 		var valLen int | 
					
						
							|  |  |  | 		switch { | 
					
						
							|  |  |  | 		case err != nil: | 
					
						
							|  |  |  | 		case fd.IsList(): | 
					
						
							|  |  |  | 			valLen, err = o.unmarshalList(b[tagLen:], wtyp, m.Mutable(fd).List(), fd) | 
					
						
							|  |  |  | 		case fd.IsMap(): | 
					
						
							|  |  |  | 			valLen, err = o.unmarshalMap(b[tagLen:], wtyp, m.Mutable(fd).Map(), fd) | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			valLen, err = o.unmarshalSingular(b[tagLen:], wtyp, m, fd) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			if err != errUnknown { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			valLen = protowire.ConsumeFieldValue(num, wtyp, b[tagLen:]) | 
					
						
							|  |  |  | 			if valLen < 0 { | 
					
						
							|  |  |  | 				return errDecode | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !o.DiscardUnknown { | 
					
						
							|  |  |  | 				m.SetUnknown(append(m.GetUnknown(), b[:tagLen+valLen]...)) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		b = b[tagLen+valLen:] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (o UnmarshalOptions) unmarshalSingular(b []byte, wtyp protowire.Type, m protoreflect.Message, fd protoreflect.FieldDescriptor) (n int, err error) { | 
					
						
							|  |  |  | 	v, n, err := o.unmarshalScalar(b, wtyp, fd) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	switch fd.Kind() { | 
					
						
							|  |  |  | 	case protoreflect.GroupKind, protoreflect.MessageKind: | 
					
						
							|  |  |  | 		m2 := m.Mutable(fd).Message() | 
					
						
							|  |  |  | 		if err := o.unmarshalMessage(v.Bytes(), m2); err != nil { | 
					
						
							|  |  |  | 			return n, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		// Non-message scalars replace the previous value. | 
					
						
							|  |  |  | 		m.Set(fd, v) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return n, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv protoreflect.Map, fd protoreflect.FieldDescriptor) (n int, err error) { | 
					
						
							|  |  |  | 	if wtyp != protowire.BytesType { | 
					
						
							|  |  |  | 		return 0, errUnknown | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	b, n = protowire.ConsumeBytes(b) | 
					
						
							|  |  |  | 	if n < 0 { | 
					
						
							|  |  |  | 		return 0, errDecode | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		keyField = fd.MapKey() | 
					
						
							|  |  |  | 		valField = fd.MapValue() | 
					
						
							|  |  |  | 		key      protoreflect.Value | 
					
						
							|  |  |  | 		val      protoreflect.Value | 
					
						
							|  |  |  | 		haveKey  bool | 
					
						
							|  |  |  | 		haveVal  bool | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	switch valField.Kind() { | 
					
						
							|  |  |  | 	case protoreflect.GroupKind, protoreflect.MessageKind: | 
					
						
							|  |  |  | 		val = mapv.NewValue() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Map entries are represented as a two-element message with fields | 
					
						
							|  |  |  | 	// containing the key and value. | 
					
						
							|  |  |  | 	for len(b) > 0 { | 
					
						
							|  |  |  | 		num, wtyp, n := protowire.ConsumeTag(b) | 
					
						
							|  |  |  | 		if n < 0 { | 
					
						
							|  |  |  | 			return 0, errDecode | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if num > protowire.MaxValidNumber { | 
					
						
							|  |  |  | 			return 0, errDecode | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		b = b[n:] | 
					
						
							|  |  |  | 		err = errUnknown | 
					
						
							|  |  |  | 		switch num { | 
					
						
							|  |  |  | 		case genid.MapEntry_Key_field_number: | 
					
						
							|  |  |  | 			key, n, err = o.unmarshalScalar(b, wtyp, keyField) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			haveKey = true | 
					
						
							|  |  |  | 		case genid.MapEntry_Value_field_number: | 
					
						
							|  |  |  | 			var v protoreflect.Value | 
					
						
							|  |  |  | 			v, n, err = o.unmarshalScalar(b, wtyp, valField) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			switch valField.Kind() { | 
					
						
							|  |  |  | 			case protoreflect.GroupKind, protoreflect.MessageKind: | 
					
						
							|  |  |  | 				if err := o.unmarshalMessage(v.Bytes(), val.Message()); err != nil { | 
					
						
							|  |  |  | 					return 0, err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				val = v | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			haveVal = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err == errUnknown { | 
					
						
							|  |  |  | 			n = protowire.ConsumeFieldValue(num, wtyp, b) | 
					
						
							|  |  |  | 			if n < 0 { | 
					
						
							|  |  |  | 				return 0, errDecode | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else if err != nil { | 
					
						
							|  |  |  | 			return 0, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		b = b[n:] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Every map entry should have entries for key and value, but this is not strictly required. | 
					
						
							|  |  |  | 	if !haveKey { | 
					
						
							|  |  |  | 		key = keyField.Default() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !haveVal { | 
					
						
							|  |  |  | 		switch valField.Kind() { | 
					
						
							|  |  |  | 		case protoreflect.GroupKind, protoreflect.MessageKind: | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			val = valField.Default() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	mapv.Set(key.MapKey(), val) | 
					
						
							|  |  |  | 	return n, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // errUnknown is used internally to indicate fields which should be added | 
					
						
							|  |  |  | // to the unknown field set of a message. It is never returned from an exported | 
					
						
							|  |  |  | // function. | 
					
						
							|  |  |  | var errUnknown = errors.New("BUG: internal error (unknown)") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var errDecode = errors.New("cannot parse invalid wire-format data") |