k8s.io/apiserver@v0.31.1/pkg/cel/value.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package cel
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"sync"
    23  	"time"
    24  
    25  	"github.com/google/cel-go/common/types"
    26  	"github.com/google/cel-go/common/types/ref"
    27  	"github.com/google/cel-go/common/types/traits"
    28  )
    29  
    30  // EncodeStyle is a hint for string encoding of parsed values.
    31  type EncodeStyle int
    32  
    33  const (
    34  	// BlockValueStyle is the default string encoding which preserves whitespace and newlines.
    35  	BlockValueStyle EncodeStyle = iota
    36  
    37  	// FlowValueStyle indicates that the string is an inline representation of complex types.
    38  	FlowValueStyle
    39  
    40  	// FoldedValueStyle is a multiline string with whitespace and newlines trimmed to a single
    41  	// a whitespace. Repeated newlines are replaced with a single newline rather than a single
    42  	// whitespace.
    43  	FoldedValueStyle
    44  
    45  	// LiteralStyle is a multiline string that preserves newlines, but trims all other whitespace
    46  	// to a single character.
    47  	LiteralStyle
    48  )
    49  
    50  // NewEmptyDynValue returns the zero-valued DynValue.
    51  func NewEmptyDynValue() *DynValue {
    52  	// note: 0 is not a valid parse node identifier.
    53  	dv, _ := NewDynValue(0, nil)
    54  	return dv
    55  }
    56  
    57  // NewDynValue returns a DynValue that corresponds to a parse node id and value.
    58  func NewDynValue(id int64, val interface{}) (*DynValue, error) {
    59  	dv := &DynValue{ID: id}
    60  	err := dv.SetValue(val)
    61  	return dv, err
    62  }
    63  
    64  // DynValue is a dynamically typed value used to describe unstructured content.
    65  // Whether the value has the desired type is determined by where it is used within the Instance or
    66  // Template, and whether there are schemas which might enforce a more rigid type definition.
    67  type DynValue struct {
    68  	ID          int64
    69  	EncodeStyle EncodeStyle
    70  	value       interface{}
    71  	exprValue   ref.Val
    72  	declType    *DeclType
    73  }
    74  
    75  // DeclType returns the policy model type of the dyn value.
    76  func (dv *DynValue) DeclType() *DeclType {
    77  	return dv.declType
    78  }
    79  
    80  // ConvertToNative is an implementation of the CEL ref.Val method used to adapt between CEL types
    81  // and Go-native types.
    82  //
    83  // The default behavior of this method is to first convert to a CEL type which has a well-defined
    84  // set of conversion behaviors and proxy to the CEL ConvertToNative method for the type.
    85  func (dv *DynValue) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
    86  	ev := dv.ExprValue()
    87  	if types.IsError(ev) {
    88  		return nil, ev.(*types.Err)
    89  	}
    90  	return ev.ConvertToNative(typeDesc)
    91  }
    92  
    93  // Equal returns whether the dyn value is equal to a given CEL value.
    94  func (dv *DynValue) Equal(other ref.Val) ref.Val {
    95  	dvType := dv.Type()
    96  	otherType := other.Type()
    97  	// Preserve CEL's homogeneous equality constraint.
    98  	if dvType.TypeName() != otherType.TypeName() {
    99  		return types.MaybeNoSuchOverloadErr(other)
   100  	}
   101  	switch v := dv.value.(type) {
   102  	case ref.Val:
   103  		return v.Equal(other)
   104  	case PlainTextValue:
   105  		return celBool(string(v) == other.Value().(string))
   106  	case *MultilineStringValue:
   107  		return celBool(v.Value == other.Value().(string))
   108  	case time.Duration:
   109  		otherDuration := other.Value().(time.Duration)
   110  		return celBool(v == otherDuration)
   111  	case time.Time:
   112  		otherTimestamp := other.Value().(time.Time)
   113  		return celBool(v.Equal(otherTimestamp))
   114  	default:
   115  		return celBool(reflect.DeepEqual(v, other.Value()))
   116  	}
   117  }
   118  
   119  // ExprValue converts the DynValue into a CEL value.
   120  func (dv *DynValue) ExprValue() ref.Val {
   121  	return dv.exprValue
   122  }
   123  
   124  // Value returns the underlying value held by this reference.
   125  func (dv *DynValue) Value() interface{} {
   126  	return dv.value
   127  }
   128  
   129  // SetValue updates the underlying value held by this reference.
   130  func (dv *DynValue) SetValue(value interface{}) error {
   131  	dv.value = value
   132  	var err error
   133  	dv.exprValue, dv.declType, err = exprValue(value)
   134  	return err
   135  }
   136  
   137  // Type returns the CEL type for the given value.
   138  func (dv *DynValue) Type() ref.Type {
   139  	return dv.ExprValue().Type()
   140  }
   141  
   142  func exprValue(value interface{}) (ref.Val, *DeclType, error) {
   143  	switch v := value.(type) {
   144  	case bool:
   145  		return types.Bool(v), BoolType, nil
   146  	case []byte:
   147  		return types.Bytes(v), BytesType, nil
   148  	case float64:
   149  		return types.Double(v), DoubleType, nil
   150  	case int64:
   151  		return types.Int(v), IntType, nil
   152  	case string:
   153  		return types.String(v), StringType, nil
   154  	case uint64:
   155  		return types.Uint(v), UintType, nil
   156  	case time.Duration:
   157  		return types.Duration{Duration: v}, DurationType, nil
   158  	case time.Time:
   159  		return types.Timestamp{Time: v}, TimestampType, nil
   160  	case types.Null:
   161  		return v, NullType, nil
   162  	case *ListValue:
   163  		return v, ListType, nil
   164  	case *MapValue:
   165  		return v, MapType, nil
   166  	case *ObjectValue:
   167  		return v, v.objectType, nil
   168  	default:
   169  		return nil, unknownType, fmt.Errorf("unsupported type: (%T)%v", v, v)
   170  	}
   171  }
   172  
   173  // PlainTextValue is a text string literal which must not be treated as an expression.
   174  type PlainTextValue string
   175  
   176  // MultilineStringValue is a multiline string value which has been parsed in a way which omits
   177  // whitespace as well as a raw form which preserves whitespace.
   178  type MultilineStringValue struct {
   179  	Value string
   180  	Raw   string
   181  }
   182  
   183  func newStructValue() *structValue {
   184  	return &structValue{
   185  		Fields:   []*Field{},
   186  		fieldMap: map[string]*Field{},
   187  	}
   188  }
   189  
   190  type structValue struct {
   191  	Fields   []*Field
   192  	fieldMap map[string]*Field
   193  }
   194  
   195  // AddField appends a MapField to the MapValue and indexes the field by name.
   196  func (sv *structValue) AddField(field *Field) {
   197  	sv.Fields = append(sv.Fields, field)
   198  	sv.fieldMap[field.Name] = field
   199  }
   200  
   201  // ConvertToNative converts the MapValue type to a native go types.
   202  func (sv *structValue) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
   203  	if typeDesc.Kind() != reflect.Map &&
   204  		typeDesc.Kind() != reflect.Struct &&
   205  		typeDesc.Kind() != reflect.Pointer &&
   206  		typeDesc.Kind() != reflect.Interface {
   207  		return nil, fmt.Errorf("type conversion error from object to '%v'", typeDesc)
   208  	}
   209  
   210  	// Unwrap pointers, but track their use.
   211  	isPtr := false
   212  	if typeDesc.Kind() == reflect.Pointer {
   213  		tk := typeDesc
   214  		typeDesc = typeDesc.Elem()
   215  		if typeDesc.Kind() == reflect.Pointer {
   216  			return nil, fmt.Errorf("unsupported type conversion to '%v'", tk)
   217  		}
   218  		isPtr = true
   219  	}
   220  
   221  	if typeDesc.Kind() == reflect.Map {
   222  		keyType := typeDesc.Key()
   223  		if keyType.Kind() != reflect.String && keyType.Kind() != reflect.Interface {
   224  			return nil, fmt.Errorf("object fields cannot be converted to type '%v'", keyType)
   225  		}
   226  		elemType := typeDesc.Elem()
   227  		sz := len(sv.fieldMap)
   228  		ntvMap := reflect.MakeMapWithSize(typeDesc, sz)
   229  		for name, val := range sv.fieldMap {
   230  			refVal, err := val.Ref.ConvertToNative(elemType)
   231  			if err != nil {
   232  				return nil, err
   233  			}
   234  			ntvMap.SetMapIndex(reflect.ValueOf(name), reflect.ValueOf(refVal))
   235  		}
   236  		return ntvMap.Interface(), nil
   237  	}
   238  
   239  	if typeDesc.Kind() == reflect.Struct {
   240  		ntvObjPtr := reflect.New(typeDesc)
   241  		ntvObj := ntvObjPtr.Elem()
   242  		for name, val := range sv.fieldMap {
   243  			f := ntvObj.FieldByName(name)
   244  			if !f.IsValid() {
   245  				return nil, fmt.Errorf("type conversion error, no such field %s in type %v",
   246  					name, typeDesc)
   247  			}
   248  			fv, err := val.Ref.ConvertToNative(f.Type())
   249  			if err != nil {
   250  				return nil, err
   251  			}
   252  			f.Set(reflect.ValueOf(fv))
   253  		}
   254  		if isPtr {
   255  			return ntvObjPtr.Interface(), nil
   256  		}
   257  		return ntvObj.Interface(), nil
   258  	}
   259  	return nil, fmt.Errorf("type conversion error from object to '%v'", typeDesc)
   260  }
   261  
   262  // GetField returns a MapField by name if one exists.
   263  func (sv *structValue) GetField(name string) (*Field, bool) {
   264  	field, found := sv.fieldMap[name]
   265  	return field, found
   266  }
   267  
   268  // IsSet returns whether the given field, which is defined, has also been set.
   269  func (sv *structValue) IsSet(key ref.Val) ref.Val {
   270  	k, ok := key.(types.String)
   271  	if !ok {
   272  		return types.MaybeNoSuchOverloadErr(key)
   273  	}
   274  	name := string(k)
   275  	_, found := sv.fieldMap[name]
   276  	return celBool(found)
   277  }
   278  
   279  // NewObjectValue creates a struct value with a schema type and returns the empty ObjectValue.
   280  func NewObjectValue(sType *DeclType) *ObjectValue {
   281  	return &ObjectValue{
   282  		structValue: newStructValue(),
   283  		objectType:  sType,
   284  	}
   285  }
   286  
   287  // ObjectValue is a struct with a custom schema type which indicates the fields and types
   288  // associated with the structure.
   289  type ObjectValue struct {
   290  	*structValue
   291  	objectType *DeclType
   292  }
   293  
   294  // ConvertToType is an implementation of the CEL ref.Val interface method.
   295  func (o *ObjectValue) ConvertToType(t ref.Type) ref.Val {
   296  	if t == types.TypeType {
   297  		return types.NewObjectTypeValue(o.objectType.TypeName())
   298  	}
   299  	if t.TypeName() == o.objectType.TypeName() {
   300  		return o
   301  	}
   302  	return types.NewErr("type conversion error from '%s' to '%s'", o.Type(), t)
   303  }
   304  
   305  // Equal returns true if the two object types are equal and their field values are equal.
   306  func (o *ObjectValue) Equal(other ref.Val) ref.Val {
   307  	// Preserve CEL's homogeneous equality semantics.
   308  	if o.objectType.TypeName() != other.Type().TypeName() {
   309  		return types.MaybeNoSuchOverloadErr(other)
   310  	}
   311  	o2 := other.(traits.Indexer)
   312  	for name := range o.objectType.Fields {
   313  		k := types.String(name)
   314  		v := o.Get(k)
   315  		ov := o2.Get(k)
   316  		vEq := v.Equal(ov)
   317  		if vEq != types.True {
   318  			return vEq
   319  		}
   320  	}
   321  	return types.True
   322  }
   323  
   324  // Get returns the value of the specified field.
   325  //
   326  // If the field is set, its value is returned. If the field is not set, the default value for the
   327  // field is returned thus allowing for safe-traversal and preserving proto-like field traversal
   328  // semantics for Open API Schema backed types.
   329  func (o *ObjectValue) Get(name ref.Val) ref.Val {
   330  	n, ok := name.(types.String)
   331  	if !ok {
   332  		return types.MaybeNoSuchOverloadErr(n)
   333  	}
   334  	nameStr := string(n)
   335  	field, found := o.fieldMap[nameStr]
   336  	if found {
   337  		return field.Ref.ExprValue()
   338  	}
   339  	fieldDef, found := o.objectType.Fields[nameStr]
   340  	if !found {
   341  		return types.NewErr("no such field: %s", nameStr)
   342  	}
   343  	defValue := fieldDef.DefaultValue()
   344  	if defValue != nil {
   345  		return defValue
   346  	}
   347  	return types.NewErr("no default for type: %s", fieldDef.TypeName())
   348  }
   349  
   350  // Type returns the CEL type value of the object.
   351  func (o *ObjectValue) Type() ref.Type {
   352  	return o.objectType
   353  }
   354  
   355  // Value returns the Go-native representation of the object.
   356  func (o *ObjectValue) Value() interface{} {
   357  	return o
   358  }
   359  
   360  // NewMapValue returns an empty MapValue.
   361  func NewMapValue() *MapValue {
   362  	return &MapValue{
   363  		structValue: newStructValue(),
   364  	}
   365  }
   366  
   367  // MapValue declares an object with a set of named fields whose values are dynamically typed.
   368  type MapValue struct {
   369  	*structValue
   370  }
   371  
   372  // ConvertToObject produces an ObjectValue from the MapValue with the associated schema type.
   373  //
   374  // The conversion is shallow and the memory shared between the Object and Map as all references
   375  // to the map are expected to be replaced with the Object reference.
   376  func (m *MapValue) ConvertToObject(declType *DeclType) *ObjectValue {
   377  	return &ObjectValue{
   378  		structValue: m.structValue,
   379  		objectType:  declType,
   380  	}
   381  }
   382  
   383  // Contains returns whether the given key is contained in the MapValue.
   384  func (m *MapValue) Contains(key ref.Val) ref.Val {
   385  	v, found := m.Find(key)
   386  	if v != nil && types.IsUnknownOrError(v) {
   387  		return v
   388  	}
   389  	return celBool(found)
   390  }
   391  
   392  // ConvertToType converts the MapValue to another CEL type, if possible.
   393  func (m *MapValue) ConvertToType(t ref.Type) ref.Val {
   394  	switch t {
   395  	case types.MapType:
   396  		return m
   397  	case types.TypeType:
   398  		return types.MapType
   399  	}
   400  	return types.NewErr("type conversion error from '%s' to '%s'", m.Type(), t)
   401  }
   402  
   403  // Equal returns true if the maps are of the same size, have the same keys, and the key-values
   404  // from each map are equal.
   405  func (m *MapValue) Equal(other ref.Val) ref.Val {
   406  	oMap, isMap := other.(traits.Mapper)
   407  	if !isMap {
   408  		return types.MaybeNoSuchOverloadErr(other)
   409  	}
   410  	if m.Size() != oMap.Size() {
   411  		return types.False
   412  	}
   413  	for name, field := range m.fieldMap {
   414  		k := types.String(name)
   415  		ov, found := oMap.Find(k)
   416  		if !found {
   417  			return types.False
   418  		}
   419  		v := field.Ref.ExprValue()
   420  		vEq := v.Equal(ov)
   421  		if vEq != types.True {
   422  			return vEq
   423  		}
   424  	}
   425  	return types.True
   426  }
   427  
   428  // Find returns the value for the key in the map, if found.
   429  func (m *MapValue) Find(name ref.Val) (ref.Val, bool) {
   430  	// Currently only maps with string keys are supported as this is best aligned with JSON,
   431  	// and also much simpler to support.
   432  	n, ok := name.(types.String)
   433  	if !ok {
   434  		return types.MaybeNoSuchOverloadErr(n), true
   435  	}
   436  	nameStr := string(n)
   437  	field, found := m.fieldMap[nameStr]
   438  	if found {
   439  		return field.Ref.ExprValue(), true
   440  	}
   441  	return nil, false
   442  }
   443  
   444  // Get returns the value for the key in the map, or error if not found.
   445  func (m *MapValue) Get(key ref.Val) ref.Val {
   446  	v, found := m.Find(key)
   447  	if found {
   448  		return v
   449  	}
   450  	return types.ValOrErr(key, "no such key: %v", key)
   451  }
   452  
   453  // Iterator produces a traits.Iterator which walks over the map keys.
   454  //
   455  // The Iterator is frequently used within comprehensions.
   456  func (m *MapValue) Iterator() traits.Iterator {
   457  	keys := make([]ref.Val, len(m.fieldMap))
   458  	i := 0
   459  	for k := range m.fieldMap {
   460  		keys[i] = types.String(k)
   461  		i++
   462  	}
   463  	return &baseMapIterator{
   464  		baseVal: &baseVal{},
   465  		keys:    keys,
   466  	}
   467  }
   468  
   469  // Size returns the number of keys in the map.
   470  func (m *MapValue) Size() ref.Val {
   471  	return types.Int(len(m.Fields))
   472  }
   473  
   474  // Type returns the CEL ref.Type for the map.
   475  func (m *MapValue) Type() ref.Type {
   476  	return types.MapType
   477  }
   478  
   479  // Value returns the Go-native representation of the MapValue.
   480  func (m *MapValue) Value() interface{} {
   481  	return m
   482  }
   483  
   484  type baseMapIterator struct {
   485  	*baseVal
   486  	keys []ref.Val
   487  	idx  int
   488  }
   489  
   490  // HasNext implements the traits.Iterator interface method.
   491  func (it *baseMapIterator) HasNext() ref.Val {
   492  	if it.idx < len(it.keys) {
   493  		return types.True
   494  	}
   495  	return types.False
   496  }
   497  
   498  // Next implements the traits.Iterator interface method.
   499  func (it *baseMapIterator) Next() ref.Val {
   500  	key := it.keys[it.idx]
   501  	it.idx++
   502  	return key
   503  }
   504  
   505  // Type implements the CEL ref.Val interface metohd.
   506  func (it *baseMapIterator) Type() ref.Type {
   507  	return types.IteratorType
   508  }
   509  
   510  // NewField returns a MapField instance with an empty DynValue that refers to the
   511  // specified parse node id and field name.
   512  func NewField(id int64, name string) *Field {
   513  	return &Field{
   514  		ID:   id,
   515  		Name: name,
   516  		Ref:  NewEmptyDynValue(),
   517  	}
   518  }
   519  
   520  // Field specifies a field name and a reference to a dynamic value.
   521  type Field struct {
   522  	ID   int64
   523  	Name string
   524  	Ref  *DynValue
   525  }
   526  
   527  // NewListValue returns an empty ListValue instance.
   528  func NewListValue() *ListValue {
   529  	return &ListValue{
   530  		Entries: []*DynValue{},
   531  	}
   532  }
   533  
   534  // ListValue contains a list of dynamically typed entries.
   535  type ListValue struct {
   536  	Entries      []*DynValue
   537  	initValueSet sync.Once
   538  	valueSet     map[ref.Val]struct{}
   539  }
   540  
   541  // Add concatenates two lists together to produce a new CEL list value.
   542  func (lv *ListValue) Add(other ref.Val) ref.Val {
   543  	oArr, isArr := other.(traits.Lister)
   544  	if !isArr {
   545  		return types.MaybeNoSuchOverloadErr(other)
   546  	}
   547  	szRight := len(lv.Entries)
   548  	szLeft := int(oArr.Size().(types.Int))
   549  	sz := szRight + szLeft
   550  	combo := make([]ref.Val, sz)
   551  	for i := 0; i < szRight; i++ {
   552  		combo[i] = lv.Entries[i].ExprValue()
   553  	}
   554  	for i := 0; i < szLeft; i++ {
   555  		combo[i+szRight] = oArr.Get(types.Int(i))
   556  	}
   557  	return types.DefaultTypeAdapter.NativeToValue(combo)
   558  }
   559  
   560  // Append adds another entry into the ListValue.
   561  func (lv *ListValue) Append(entry *DynValue) {
   562  	lv.Entries = append(lv.Entries, entry)
   563  	// The append resets all previously built indices.
   564  	lv.initValueSet = sync.Once{}
   565  }
   566  
   567  // Contains returns whether the input `val` is equal to an element in the list.
   568  //
   569  // If any pair-wise comparison between the input value and the list element is an error, the
   570  // operation will return an error.
   571  func (lv *ListValue) Contains(val ref.Val) ref.Val {
   572  	if types.IsUnknownOrError(val) {
   573  		return val
   574  	}
   575  	lv.initValueSet.Do(lv.finalizeValueSet)
   576  	if lv.valueSet != nil {
   577  		_, found := lv.valueSet[val]
   578  		if found {
   579  			return types.True
   580  		}
   581  		// Instead of returning false, ensure that CEL's heterogeneous equality constraint
   582  		// is satisfied by allowing pair-wise equality behavior to determine the outcome.
   583  	}
   584  	var err ref.Val
   585  	sz := len(lv.Entries)
   586  	for i := 0; i < sz; i++ {
   587  		elem := lv.Entries[i]
   588  		cmp := elem.Equal(val)
   589  		b, ok := cmp.(types.Bool)
   590  		if !ok && err == nil {
   591  			err = types.MaybeNoSuchOverloadErr(cmp)
   592  		}
   593  		if b == types.True {
   594  			return types.True
   595  		}
   596  	}
   597  	if err != nil {
   598  		return err
   599  	}
   600  	return types.False
   601  }
   602  
   603  // ConvertToNative is an implementation of the CEL ref.Val method used to adapt between CEL types
   604  // and Go-native array-like types.
   605  func (lv *ListValue) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
   606  	// Non-list conversion.
   607  	if typeDesc.Kind() != reflect.Slice &&
   608  		typeDesc.Kind() != reflect.Array &&
   609  		typeDesc.Kind() != reflect.Interface {
   610  		return nil, fmt.Errorf("type conversion error from list to '%v'", typeDesc)
   611  	}
   612  
   613  	// If the list is already assignable to the desired type return it.
   614  	if reflect.TypeOf(lv).AssignableTo(typeDesc) {
   615  		return lv, nil
   616  	}
   617  
   618  	// List conversion.
   619  	otherElem := typeDesc.Elem()
   620  
   621  	// Allow the element ConvertToNative() function to determine whether conversion is possible.
   622  	sz := len(lv.Entries)
   623  	nativeList := reflect.MakeSlice(typeDesc, int(sz), int(sz))
   624  	for i := 0; i < sz; i++ {
   625  		elem := lv.Entries[i]
   626  		nativeElemVal, err := elem.ConvertToNative(otherElem)
   627  		if err != nil {
   628  			return nil, err
   629  		}
   630  		nativeList.Index(int(i)).Set(reflect.ValueOf(nativeElemVal))
   631  	}
   632  	return nativeList.Interface(), nil
   633  }
   634  
   635  // ConvertToType converts the ListValue to another CEL type.
   636  func (lv *ListValue) ConvertToType(t ref.Type) ref.Val {
   637  	switch t {
   638  	case types.ListType:
   639  		return lv
   640  	case types.TypeType:
   641  		return types.ListType
   642  	}
   643  	return types.NewErr("type conversion error from '%s' to '%s'", ListType, t)
   644  }
   645  
   646  // Equal returns true if two lists are of the same size, and the values at each index are also
   647  // equal.
   648  func (lv *ListValue) Equal(other ref.Val) ref.Val {
   649  	oArr, isArr := other.(traits.Lister)
   650  	if !isArr {
   651  		return types.MaybeNoSuchOverloadErr(other)
   652  	}
   653  	sz := types.Int(len(lv.Entries))
   654  	if sz != oArr.Size() {
   655  		return types.False
   656  	}
   657  	for i := types.Int(0); i < sz; i++ {
   658  		cmp := lv.Get(i).Equal(oArr.Get(i))
   659  		if cmp != types.True {
   660  			return cmp
   661  		}
   662  	}
   663  	return types.True
   664  }
   665  
   666  // Get returns the value at the given index.
   667  //
   668  // If the index is negative or greater than the size of the list, an error is returned.
   669  func (lv *ListValue) Get(idx ref.Val) ref.Val {
   670  	iv, isInt := idx.(types.Int)
   671  	if !isInt {
   672  		return types.ValOrErr(idx, "unsupported index: %v", idx)
   673  	}
   674  	i := int(iv)
   675  	if i < 0 || i >= len(lv.Entries) {
   676  		return types.NewErr("index out of bounds: %v", idx)
   677  	}
   678  	return lv.Entries[i].ExprValue()
   679  }
   680  
   681  // Iterator produces a traits.Iterator suitable for use in CEL comprehension macros.
   682  func (lv *ListValue) Iterator() traits.Iterator {
   683  	return &baseListIterator{
   684  		getter: lv.Get,
   685  		sz:     len(lv.Entries),
   686  	}
   687  }
   688  
   689  // Size returns the number of elements in the list.
   690  func (lv *ListValue) Size() ref.Val {
   691  	return types.Int(len(lv.Entries))
   692  }
   693  
   694  // Type returns the CEL ref.Type for the list.
   695  func (lv *ListValue) Type() ref.Type {
   696  	return types.ListType
   697  }
   698  
   699  // Value returns the Go-native value.
   700  func (lv *ListValue) Value() interface{} {
   701  	return lv
   702  }
   703  
   704  // finalizeValueSet inspects the ListValue entries in order to make internal optimizations once all list
   705  // entries are known.
   706  func (lv *ListValue) finalizeValueSet() {
   707  	valueSet := make(map[ref.Val]struct{})
   708  	for _, e := range lv.Entries {
   709  		switch e.value.(type) {
   710  		case bool, float64, int64, string, uint64, types.Null, PlainTextValue:
   711  			valueSet[e.ExprValue()] = struct{}{}
   712  		default:
   713  			lv.valueSet = nil
   714  			return
   715  		}
   716  	}
   717  	lv.valueSet = valueSet
   718  }
   719  
   720  type baseVal struct{}
   721  
   722  func (*baseVal) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
   723  	return nil, fmt.Errorf("unsupported native conversion to: %v", typeDesc)
   724  }
   725  
   726  func (*baseVal) ConvertToType(t ref.Type) ref.Val {
   727  	return types.NewErr("unsupported type conversion to: %v", t)
   728  }
   729  
   730  func (*baseVal) Equal(other ref.Val) ref.Val {
   731  	return types.NewErr("unsupported equality test between instances")
   732  }
   733  
   734  func (v *baseVal) Value() interface{} {
   735  	return nil
   736  }
   737  
   738  type baseListIterator struct {
   739  	*baseVal
   740  	getter func(idx ref.Val) ref.Val
   741  	sz     int
   742  	idx    int
   743  }
   744  
   745  func (it *baseListIterator) HasNext() ref.Val {
   746  	if it.idx < it.sz {
   747  		return types.True
   748  	}
   749  	return types.False
   750  }
   751  
   752  func (it *baseListIterator) Next() ref.Val {
   753  	v := it.getter(types.Int(it.idx))
   754  	it.idx++
   755  	return v
   756  }
   757  
   758  func (it *baseListIterator) Type() ref.Type {
   759  	return types.IteratorType
   760  }
   761  
   762  func celBool(pred bool) ref.Val {
   763  	if pred {
   764  		return types.True
   765  	}
   766  	return types.False
   767  }
   768  
   769  var unknownType = &DeclType{name: "unknown", MinSerializedSize: 1}