gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

extension.go (2973B)


      1 // Copyright 2019 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package proto
      6 
      7 import (
      8 	"google.golang.org/protobuf/reflect/protoreflect"
      9 )
     10 
     11 // HasExtension reports whether an extension field is populated.
     12 // It returns false if m is invalid or if xt does not extend m.
     13 func HasExtension(m Message, xt protoreflect.ExtensionType) bool {
     14 	// Treat nil message interface as an empty message; no populated fields.
     15 	if m == nil {
     16 		return false
     17 	}
     18 
     19 	// As a special-case, we reports invalid or mismatching descriptors
     20 	// as always not being populated (since they aren't).
     21 	if xt == nil || m.ProtoReflect().Descriptor() != xt.TypeDescriptor().ContainingMessage() {
     22 		return false
     23 	}
     24 
     25 	return m.ProtoReflect().Has(xt.TypeDescriptor())
     26 }
     27 
     28 // ClearExtension clears an extension field such that subsequent
     29 // HasExtension calls return false.
     30 // It panics if m is invalid or if xt does not extend m.
     31 func ClearExtension(m Message, xt protoreflect.ExtensionType) {
     32 	m.ProtoReflect().Clear(xt.TypeDescriptor())
     33 }
     34 
     35 // GetExtension retrieves the value for an extension field.
     36 // If the field is unpopulated, it returns the default value for
     37 // scalars and an immutable, empty value for lists or messages.
     38 // It panics if xt does not extend m.
     39 func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} {
     40 	// Treat nil message interface as an empty message; return the default.
     41 	if m == nil {
     42 		return xt.InterfaceOf(xt.Zero())
     43 	}
     44 
     45 	return xt.InterfaceOf(m.ProtoReflect().Get(xt.TypeDescriptor()))
     46 }
     47 
     48 // SetExtension stores the value of an extension field.
     49 // It panics if m is invalid, xt does not extend m, or if type of v
     50 // is invalid for the specified extension field.
     51 func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) {
     52 	xd := xt.TypeDescriptor()
     53 	pv := xt.ValueOf(v)
     54 
     55 	// Specially treat an invalid list, map, or message as clear.
     56 	isValid := true
     57 	switch {
     58 	case xd.IsList():
     59 		isValid = pv.List().IsValid()
     60 	case xd.IsMap():
     61 		isValid = pv.Map().IsValid()
     62 	case xd.Message() != nil:
     63 		isValid = pv.Message().IsValid()
     64 	}
     65 	if !isValid {
     66 		m.ProtoReflect().Clear(xd)
     67 		return
     68 	}
     69 
     70 	m.ProtoReflect().Set(xd, pv)
     71 }
     72 
     73 // RangeExtensions iterates over every populated extension field in m in an
     74 // undefined order, calling f for each extension type and value encountered.
     75 // It returns immediately if f returns false.
     76 // While iterating, mutating operations may only be performed
     77 // on the current extension field.
     78 func RangeExtensions(m Message, f func(protoreflect.ExtensionType, interface{}) bool) {
     79 	// Treat nil message interface as an empty message; nothing to range over.
     80 	if m == nil {
     81 		return
     82 	}
     83 
     84 	m.ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
     85 		if fd.IsExtension() {
     86 			xt := fd.(protoreflect.ExtensionTypeDescriptor).Type()
     87 			vi := xt.InterfaceOf(v)
     88 			return f(xt, vi)
     89 		}
     90 		return true
     91 	})
     92 }