| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | // Copyright 2019 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/reflect/protoreflect" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // HasExtension reports whether an extension field is populated. | 
					
						
							|  |  |  | // It returns false if m is invalid or if xt does not extend m. | 
					
						
							|  |  |  | func HasExtension(m Message, xt protoreflect.ExtensionType) bool { | 
					
						
							| 
									
										
										
										
											2024-05-06 08:50:47 +00:00
										 |  |  | 	// Treat nil message interface or descriptor as an empty message; no populated | 
					
						
							|  |  |  | 	// fields. | 
					
						
							|  |  |  | 	if m == nil || xt == nil { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// As a special-case, we reports invalid or mismatching descriptors | 
					
						
							|  |  |  | 	// as always not being populated (since they aren't). | 
					
						
							| 
									
										
										
										
											2024-05-06 08:50:47 +00:00
										 |  |  | 	mr := m.ProtoReflect() | 
					
						
							|  |  |  | 	xd := xt.TypeDescriptor() | 
					
						
							|  |  |  | 	if mr.Descriptor() != xd.ContainingMessage() { | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-06 08:50:47 +00:00
										 |  |  | 	return mr.Has(xd) | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ClearExtension clears an extension field such that subsequent | 
					
						
							| 
									
										
										
										
											2024-03-11 10:12:06 +00:00
										 |  |  | // [HasExtension] calls return false. | 
					
						
							| 
									
										
										
										
											2021-08-12 21:03:24 +02:00
										 |  |  | // It panics if m is invalid or if xt does not extend m. | 
					
						
							|  |  |  | func ClearExtension(m Message, xt protoreflect.ExtensionType) { | 
					
						
							|  |  |  | 	m.ProtoReflect().Clear(xt.TypeDescriptor()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetExtension retrieves the value for an extension field. | 
					
						
							|  |  |  | // If the field is unpopulated, it returns the default value for | 
					
						
							|  |  |  | // scalars and an immutable, empty value for lists or messages. | 
					
						
							|  |  |  | // It panics if xt does not extend m. | 
					
						
							|  |  |  | func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} { | 
					
						
							|  |  |  | 	// Treat nil message interface as an empty message; return the default. | 
					
						
							|  |  |  | 	if m == nil { | 
					
						
							|  |  |  | 		return xt.InterfaceOf(xt.Zero()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return xt.InterfaceOf(m.ProtoReflect().Get(xt.TypeDescriptor())) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetExtension stores the value of an extension field. | 
					
						
							|  |  |  | // It panics if m is invalid, xt does not extend m, or if type of v | 
					
						
							|  |  |  | // is invalid for the specified extension field. | 
					
						
							|  |  |  | func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) { | 
					
						
							|  |  |  | 	xd := xt.TypeDescriptor() | 
					
						
							|  |  |  | 	pv := xt.ValueOf(v) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Specially treat an invalid list, map, or message as clear. | 
					
						
							|  |  |  | 	isValid := true | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case xd.IsList(): | 
					
						
							|  |  |  | 		isValid = pv.List().IsValid() | 
					
						
							|  |  |  | 	case xd.IsMap(): | 
					
						
							|  |  |  | 		isValid = pv.Map().IsValid() | 
					
						
							|  |  |  | 	case xd.Message() != nil: | 
					
						
							|  |  |  | 		isValid = pv.Message().IsValid() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !isValid { | 
					
						
							|  |  |  | 		m.ProtoReflect().Clear(xd) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m.ProtoReflect().Set(xd, pv) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // RangeExtensions iterates over every populated extension field in m in an | 
					
						
							|  |  |  | // undefined order, calling f for each extension type and value encountered. | 
					
						
							|  |  |  | // It returns immediately if f returns false. | 
					
						
							|  |  |  | // While iterating, mutating operations may only be performed | 
					
						
							|  |  |  | // on the current extension field. | 
					
						
							|  |  |  | func RangeExtensions(m Message, f func(protoreflect.ExtensionType, interface{}) bool) { | 
					
						
							|  |  |  | 	// Treat nil message interface as an empty message; nothing to range over. | 
					
						
							|  |  |  | 	if m == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m.ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { | 
					
						
							|  |  |  | 		if fd.IsExtension() { | 
					
						
							|  |  |  | 			xt := fd.(protoreflect.ExtensionTypeDescriptor).Type() | 
					
						
							|  |  |  | 			vi := xt.InterfaceOf(v) | 
					
						
							|  |  |  | 			return f(xt, vi) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } |