mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			133 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package cty
 | 
						|
 | 
						|
import (
 | 
						|
	"reflect"
 | 
						|
)
 | 
						|
 | 
						|
// CapsuleOps represents a set of overloaded operations for a capsule type.
 | 
						|
//
 | 
						|
// Each field is a reference to a function that can either be nil or can be
 | 
						|
// set to an implementation of the corresponding operation. If an operation
 | 
						|
// function is nil then it isn't supported for the given capsule type.
 | 
						|
type CapsuleOps struct {
 | 
						|
	// GoString provides the GoString implementation for values of the
 | 
						|
	// corresponding type. Conventionally this should return a string
 | 
						|
	// representation of an expression that would produce an equivalent
 | 
						|
	// value.
 | 
						|
	GoString func(val interface{}) string
 | 
						|
 | 
						|
	// TypeGoString provides the GoString implementation for the corresponding
 | 
						|
	// capsule type itself.
 | 
						|
	TypeGoString func(goTy reflect.Type) string
 | 
						|
 | 
						|
	// Equals provides the implementation of the Equals operation. This is
 | 
						|
	// called only with known, non-null values of the corresponding type,
 | 
						|
	// but if the corresponding type is a compound type then it must be
 | 
						|
	// ready to detect and handle nested unknown or null values, usually
 | 
						|
	// by recursively calling Value.Equals on those nested values.
 | 
						|
	//
 | 
						|
	// The result value must always be of type cty.Bool, or the Equals
 | 
						|
	// operation will panic.
 | 
						|
	//
 | 
						|
	// If RawEquals is set without also setting Equals, the RawEquals
 | 
						|
	// implementation will be used as a fallback implementation. That fallback
 | 
						|
	// is appropriate only for leaf types that do not contain any nested
 | 
						|
	// cty.Value that would need to distinguish Equals vs. RawEquals for their
 | 
						|
	// own equality.
 | 
						|
	//
 | 
						|
	// If RawEquals is nil then Equals must also be nil, selecting the default
 | 
						|
	// pointer-identity comparison instead.
 | 
						|
	Equals func(a, b interface{}) Value
 | 
						|
 | 
						|
	// RawEquals provides the implementation of the RawEquals operation.
 | 
						|
	// This is called only with known, non-null values of the corresponding
 | 
						|
	// type, but if the corresponding type is a compound type then it must be
 | 
						|
	// ready to detect and handle nested unknown or null values, usually
 | 
						|
	// by recursively calling Value.RawEquals on those nested values.
 | 
						|
	//
 | 
						|
	// If RawEquals is nil, values of the corresponding type are compared by
 | 
						|
	// pointer identity of the encapsulated value.
 | 
						|
	RawEquals func(a, b interface{}) bool
 | 
						|
 | 
						|
	// ConversionFrom can provide conversions from the corresponding type to
 | 
						|
	// some other type when values of the corresponding type are used with
 | 
						|
	// the "convert" package. (The main cty package does not use this operation.)
 | 
						|
	//
 | 
						|
	// This function itself returns a function, allowing it to switch its
 | 
						|
	// behavior depending on the given source type. Return nil to indicate
 | 
						|
	// that no such conversion is available.
 | 
						|
	ConversionFrom func(src Type) func(interface{}, Path) (Value, error)
 | 
						|
 | 
						|
	// ConversionTo can provide conversions to the corresponding type from
 | 
						|
	// some other type when values of the corresponding type are used with
 | 
						|
	// the "convert" package. (The main cty package does not use this operation.)
 | 
						|
	//
 | 
						|
	// This function itself returns a function, allowing it to switch its
 | 
						|
	// behavior depending on the given destination type. Return nil to indicate
 | 
						|
	// that no such conversion is available.
 | 
						|
	ConversionTo func(dst Type) func(Value, Path) (interface{}, error)
 | 
						|
 | 
						|
	// ExtensionData is an extension point for applications that wish to
 | 
						|
	// create their own extension features using capsule types.
 | 
						|
	//
 | 
						|
	// The key argument is any value that can be compared with Go's ==
 | 
						|
	// operator, but should be of a named type in a package belonging to the
 | 
						|
	// application defining the key. An ExtensionData implementation must
 | 
						|
	// check to see if the given key is familar to it, and if so return a
 | 
						|
	// suitable value for the key.
 | 
						|
	//
 | 
						|
	// If the given key is unrecognized, the ExtensionData function must
 | 
						|
	// return a nil interface. (Importantly, not an interface containing a nil
 | 
						|
	// pointer of some other type.)
 | 
						|
	// The common implementation of ExtensionData is a single switch statement
 | 
						|
	// over "key" which has a default case returning nil.
 | 
						|
	//
 | 
						|
	// The meaning of any given key is entirely up to the application that
 | 
						|
	// defines it. Applications consuming ExtensionData from capsule types
 | 
						|
	// should do so defensively: if the result of ExtensionData is not valid,
 | 
						|
	// prefer to ignore it or gracefully produce an error rather than causing
 | 
						|
	// a panic.
 | 
						|
	ExtensionData func(key interface{}) interface{}
 | 
						|
}
 | 
						|
 | 
						|
// noCapsuleOps is a pointer to a CapsuleOps with no functions set, which
 | 
						|
// is used as the default operations value when a type is created using
 | 
						|
// the Capsule function.
 | 
						|
var noCapsuleOps = &CapsuleOps{}
 | 
						|
 | 
						|
func (ops *CapsuleOps) assertValid() {
 | 
						|
	if ops.RawEquals == nil && ops.Equals != nil {
 | 
						|
		panic("Equals cannot be set without RawEquals")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// CapsuleOps returns a pointer to the CapsuleOps value for a capsule type,
 | 
						|
// or panics if the receiver is not a capsule type.
 | 
						|
//
 | 
						|
// The caller must not modify the CapsuleOps.
 | 
						|
func (ty Type) CapsuleOps() *CapsuleOps {
 | 
						|
	if !ty.IsCapsuleType() {
 | 
						|
		panic("not a capsule-typed value")
 | 
						|
	}
 | 
						|
 | 
						|
	return ty.typeImpl.(*capsuleType).Ops
 | 
						|
}
 | 
						|
 | 
						|
// CapsuleExtensionData is a convenience interface to the ExtensionData
 | 
						|
// function that can be optionally implemented for a capsule type. It will
 | 
						|
// check to see if the underlying type implements ExtensionData and call it
 | 
						|
// if so. If not, it will return nil to indicate that the given key is not
 | 
						|
// supported.
 | 
						|
//
 | 
						|
// See the documentation for CapsuleOps.ExtensionData for more information
 | 
						|
// on the purpose of and usage of this mechanism.
 | 
						|
//
 | 
						|
// If CapsuleExtensionData is called on a non-capsule type then it will panic.
 | 
						|
func (ty Type) CapsuleExtensionData(key interface{}) interface{} {
 | 
						|
	ops := ty.CapsuleOps()
 | 
						|
	if ops.ExtensionData == nil {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	return ops.ExtensionData(key)
 | 
						|
}
 |