func (it *stringKeyIterator) Next() ref.Val {
	if it.HasNext() == True {
		index := it.cursor
		it.cursor++
		return String(it.mapKeys[index])
	}
	return nil
}
Next implements the traits.Iterator interface method.
package types
import (
	"fmt"
	"reflect"
	"github.com/google/cel-go/common/types/pb"
	"github.com/google/cel-go/common/types/ref"
	"github.com/google/cel-go/common/types/traits"
	"github.com/stoewer/go-strcase"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
	anypb "google.golang.org/protobuf/types/known/anypb"
	structpb "google.golang.org/protobuf/types/known/structpb"
)
func NewDynamicMap(adapter ref.TypeAdapter, value interface{}) traits.Mapper {
	refValue := reflect.ValueOf(value)
	return &baseMap{
		TypeAdapter: adapter,
		mapAccessor: newReflectMapAccessor(adapter, refValue),
		value:       value,
		size:        refValue.Len(),
	}
}
func NewJSONStruct(adapter ref.TypeAdapter, value *structpb.Struct) traits.Mapper {
	fields := value.GetFields()
	return &baseMap{
		TypeAdapter: adapter,
		mapAccessor: newJSONStructAccessor(adapter, fields),
		value:       value,
		size:        len(fields),
	}
}
func NewRefValMap(adapter ref.TypeAdapter, value map[ref.Val]ref.Val) traits.Mapper {
	return &baseMap{
		TypeAdapter: adapter,
		mapAccessor: newRefValMapAccessor(value),
		value:       value,
		size:        len(value),
	}
}
func NewStringInterfaceMap(adapter ref.TypeAdapter, value map[string]interface{}) traits.Mapper {
	return &baseMap{
		TypeAdapter: adapter,
		mapAccessor: newStringIfaceMapAccessor(adapter, value),
		value:       value,
		size:        len(value),
	}
}
func NewStringStringMap(adapter ref.TypeAdapter, value map[string]string) traits.Mapper {
	return &baseMap{
		TypeAdapter: adapter,
		mapAccessor: newStringMapAccessor(value),
		value:       value,
		size:        len(value),
	}
}
func NewProtoMap(adapter ref.TypeAdapter, value *pb.Map) traits.Mapper {
	return &protoMap{
		TypeAdapter: adapter,
		value:       value,
	}
}
var (
	MapType = NewTypeValue("map",
		traits.ContainerType,
		traits.IndexerType,
		traits.IterableType,
		traits.SizerType)
)
type mapAccessor interface {
	Find(ref.Val) (ref.Val, bool)
	Iterator() traits.Iterator
}
type baseMap struct {
	ref.TypeAdapter
	mapAccessor
	value interface{}
	size int
}
func (m *baseMap) Contains(index ref.Val) ref.Val {
	val, found := m.Find(index)
	if !found && val != nil && IsUnknownOrError(val) {
		return val
	}
	return Bool(found)
}
func (m *baseMap) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
	if reflect.TypeOf(m.value).AssignableTo(typeDesc) {
		return m.value, nil
	}
	if reflect.TypeOf(m).AssignableTo(typeDesc) {
		return m, nil
	}
	switch typeDesc {
	case anyValueType:
		json, err := m.ConvertToNative(jsonStructType)
		if err != nil {
			return nil, err
		}
		return anypb.New(json.(proto.Message))
	case jsonValueType, jsonStructType:
		jsonEntries, err :=
			m.ConvertToNative(reflect.TypeOf(map[string]*structpb.Value{}))
		if err != nil {
			return nil, err
		}
		jsonMap := &structpb.Struct{Fields: jsonEntries.(map[string]*structpb.Value)}
		if typeDesc == jsonStructType {
			return jsonMap, nil
		}
		return structpb.NewStructValue(jsonMap), nil
	}
	isPtr := false
	if typeDesc.Kind() == reflect.Ptr {
		tk := typeDesc
		typeDesc = typeDesc.Elem()
		if typeDesc.Kind() == reflect.Ptr {
			return nil, fmt.Errorf("unsupported type conversion to '%v'", tk)
		}
		isPtr = true
	}
	switch typeDesc.Kind() {
	case reflect.Map:
		otherKey := typeDesc.Key()
		otherElem := typeDesc.Elem()
		nativeMap := reflect.MakeMapWithSize(typeDesc, m.size)
		it := m.Iterator()
		for it.HasNext() == True {
			key := it.Next()
			refKeyValue, err := key.ConvertToNative(otherKey)
			if err != nil {
				return nil, err
			}
			refElemValue, err := m.Get(key).ConvertToNative(otherElem)
			if err != nil {
				return nil, err
			}
			nativeMap.SetMapIndex(reflect.ValueOf(refKeyValue), reflect.ValueOf(refElemValue))
		}
		return nativeMap.Interface(), nil
	case reflect.Struct:
		nativeStructPtr := reflect.New(typeDesc)
		nativeStruct := nativeStructPtr.Elem()
		it := m.Iterator()
		for it.HasNext() == True {
			key := it.Next()
			fieldName := key.ConvertToType(StringType)
			if IsError(fieldName) {
				return nil, fieldName.(*Err)
			}
			name := string(fieldName.(String))
			name = strcase.UpperCamelCase(name)
			fieldRef := nativeStruct.FieldByName(name)
			if !fieldRef.IsValid() {
				return nil, fmt.Errorf("type conversion error, no such field '%s' in type '%v'", name, typeDesc)
			}
			fieldValue, err := m.Get(key).ConvertToNative(fieldRef.Type())
			if err != nil {
				return nil, err
			}
			fieldRef.Set(reflect.ValueOf(fieldValue))
		}
		if isPtr {
			return nativeStructPtr.Interface(), nil
		}
		return nativeStruct.Interface(), nil
	}
	return nil, fmt.Errorf("type conversion error from map to '%v'", typeDesc)
}
func (m *baseMap) ConvertToType(typeVal ref.Type) ref.Val {
	switch typeVal {
	case MapType:
		return m
	case TypeType:
		return MapType
	}
	return NewErr("type conversion error from '%s' to '%s'", MapType, typeVal)
}
func (m *baseMap) Equal(other ref.Val) ref.Val {
	otherMap, ok := other.(traits.Mapper)
	if !ok {
		return MaybeNoSuchOverloadErr(other)
	}
	if m.Size() != otherMap.Size() {
		return False
	}
	it := m.Iterator()
	var maybeErr ref.Val
	for it.HasNext() == True {
		key := it.Next()
		thisVal, _ := m.Find(key)
		otherVal, found := otherMap.Find(key)
		if !found {
			if otherVal == nil {
				return False
			}
			if maybeErr == nil {
				maybeErr = MaybeNoSuchOverloadErr(otherVal)
			}
			continue
		}
		valEq := thisVal.Equal(otherVal)
		if valEq == False {
			return False
		}
		if maybeErr == nil && IsUnknownOrError(valEq) {
			maybeErr = valEq
		}
	}
	if maybeErr != nil {
		return maybeErr
	}
	return True
}
func (m *baseMap) Get(key ref.Val) ref.Val {
	v, found := m.Find(key)
	if !found {
		return ValOrErr(v, "no such key: %v", key)
	}
	return v
}
func (m *baseMap) Size() ref.Val {
	return Int(m.size)
}
func (m *baseMap) Type() ref.Type {
	return MapType
}
func (m *baseMap) Value() interface{} {
	return m.value
}
func newJSONStructAccessor(adapter ref.TypeAdapter, st map[string]*structpb.Value) mapAccessor {
	return &jsonStructAccessor{
		TypeAdapter: adapter,
		st:          st,
	}
}
type jsonStructAccessor struct {
	ref.TypeAdapter
	st map[string]*structpb.Value
}
func (a *jsonStructAccessor) Find(key ref.Val) (ref.Val, bool) {
	strKey, ok := key.(String)
	if !ok {
		return ValOrErr(key, "unsupported key type: %v", key.Type()), false
	}
	keyVal, found := a.st[string(strKey)]
	if !found {
		return nil, false
	}
	return a.NativeToValue(keyVal), true
}
func (a *jsonStructAccessor) Iterator() traits.Iterator {
	mapKeys := make([]string, len(a.st))
	i := 0
	for k := range a.st {
		mapKeys[i] = k
		i++
	}
	return &stringKeyIterator{
		mapKeys: mapKeys,
		len:     len(mapKeys),
	}
}
func newReflectMapAccessor(adapter ref.TypeAdapter, value reflect.Value) mapAccessor {
	keyType := value.Type().Key()
	return &reflectMapAccessor{
		TypeAdapter: adapter,
		refValue:    value,
		keyType:     keyType,
	}
}
type reflectMapAccessor struct {
	ref.TypeAdapter
	refValue reflect.Value
	keyType  reflect.Type
}
func (a *reflectMapAccessor) Find(key ref.Val) (ref.Val, bool) {
	if IsUnknownOrError(key) {
		return MaybeNoSuchOverloadErr(key), false
	}
	if a.refValue.Len() == 0 {
		return nil, false
	}
	k, err := key.ConvertToNative(a.keyType)
	if err != nil {
		return NewErr("unsupported key type: %v", key.Type()), false
	}
	refKey := reflect.ValueOf(k)
	val := a.refValue.MapIndex(refKey)
	if val.IsValid() {
		return a.NativeToValue(val.Interface()), true
	}
	mapIt := a.refValue.MapRange()
	for mapIt.Next() {
		if refKey.Kind() == mapIt.Key().Kind() {
			return nil, false
		}
	}
	return NewErr("unsupported key type: %v", key.Type()), false
}
func (a *reflectMapAccessor) Iterator() traits.Iterator {
	return &mapIterator{
		TypeAdapter: a.TypeAdapter,
		mapKeys:     a.refValue.MapRange(),
		len:         a.refValue.Len(),
	}
}
func newRefValMapAccessor(mapVal map[ref.Val]ref.Val) mapAccessor {
	return &refValMapAccessor{mapVal: mapVal}
}
type refValMapAccessor struct {
	mapVal map[ref.Val]ref.Val
}
func (a *refValMapAccessor) Find(key ref.Val) (ref.Val, bool) {
	if IsUnknownOrError(key) {
		return key, false
	}
	if len(a.mapVal) == 0 {
		return nil, false
	}
	keyVal, found := a.mapVal[key]
	if found {
		return keyVal, true
	}
	for k := range a.mapVal {
		if k.Type().TypeName() == key.Type().TypeName() {
			return nil, false
		}
	}
	return NewErr("unsupported key type: %v", key.Type()), found
}
func (a *refValMapAccessor) Iterator() traits.Iterator {
	return &mapIterator{
		TypeAdapter: DefaultTypeAdapter,
		mapKeys:     reflect.ValueOf(a.mapVal).MapRange(),
		len:         len(a.mapVal),
	}
}
func newStringMapAccessor(strMap map[string]string) mapAccessor {
	return &stringMapAccessor{mapVal: strMap}
}
type stringMapAccessor struct {
	mapVal map[string]string
}
func (a *stringMapAccessor) Find(key ref.Val) (ref.Val, bool) {
	strKey, ok := key.(String)
	if !ok {
		return ValOrErr(key, "unsupported key type: %v", key.Type()), false
	}
	keyVal, found := a.mapVal[string(strKey)]
	if !found {
		return nil, false
	}
	return String(keyVal), true
}
func (a *stringMapAccessor) Iterator() traits.Iterator {
	mapKeys := make([]string, len(a.mapVal))
	i := 0
	for k := range a.mapVal {
		mapKeys[i] = k
		i++
	}
	return &stringKeyIterator{
		mapKeys: mapKeys,
		len:     len(mapKeys),
	}
}
func newStringIfaceMapAccessor(adapter ref.TypeAdapter, mapVal map[string]interface{}) mapAccessor {
	return &stringIfaceMapAccessor{
		TypeAdapter: adapter,
		mapVal:      mapVal,
	}
}
type stringIfaceMapAccessor struct {
	ref.TypeAdapter
	mapVal map[string]interface{}
}
func (a *stringIfaceMapAccessor) Find(key ref.Val) (ref.Val, bool) {
	strKey, ok := key.(String)
	if !ok {
		return ValOrErr(key, "unsupported key type: %v", key.Type()), false
	}
	keyVal, found := a.mapVal[string(strKey)]
	if !found {
		return nil, false
	}
	return a.NativeToValue(keyVal), true
}
func (a *stringIfaceMapAccessor) Iterator() traits.Iterator {
	mapKeys := make([]string, len(a.mapVal))
	i := 0
	for k := range a.mapVal {
		mapKeys[i] = k
		i++
	}
	return &stringKeyIterator{
		mapKeys: mapKeys,
		len:     len(mapKeys),
	}
}
type protoMap struct {
	ref.TypeAdapter
	value *pb.Map
}
func (m *protoMap) Contains(key ref.Val) ref.Val {
	val, found := m.Find(key)
	if !found && val != nil && IsUnknownOrError(val) {
		return val
	}
	return Bool(found)
}
func (m *protoMap) ConvertToNative(typeDesc reflect.Type) (interface{}, error) {
	switch typeDesc {
	case anyValueType:
		json, err := m.ConvertToNative(jsonStructType)
		if err != nil {
			return nil, err
		}
		return anypb.New(json.(proto.Message))
	case jsonValueType, jsonStructType:
		jsonEntries, err :=
			m.ConvertToNative(reflect.TypeOf(map[string]*structpb.Value{}))
		if err != nil {
			return nil, err
		}
		jsonMap := &structpb.Struct{
			Fields: jsonEntries.(map[string]*structpb.Value)}
		if typeDesc == jsonStructType {
			return jsonMap, nil
		}
		return structpb.NewStructValue(jsonMap), nil
	}
	switch typeDesc.Kind() {
	case reflect.Struct, reflect.Ptr:
		if reflect.TypeOf(m.value).AssignableTo(typeDesc) {
			return m.value, nil
		}
		if reflect.TypeOf(m).AssignableTo(typeDesc) {
			return m, nil
		}
	}
	if typeDesc.Kind() != reflect.Map {
		return nil, fmt.Errorf("unsupported type conversion: %v to map", typeDesc)
	}
	keyType := m.value.KeyType.ReflectType()
	valType := m.value.ValueType.ReflectType()
	otherKeyType := typeDesc.Key()
	otherValType := typeDesc.Elem()
	mapVal := reflect.MakeMapWithSize(typeDesc, m.value.Len())
	var err error
	m.value.Range(func(key protoreflect.MapKey, val protoreflect.Value) bool {
		ntvKey := key.Interface()
		ntvVal := val.Interface()
		switch ntvVal.(type) {
		case protoreflect.Message:
			ntvVal = ntvVal.(protoreflect.Message).Interface()
		}
		if keyType == otherKeyType && valType == otherValType {
			mapVal.SetMapIndex(reflect.ValueOf(ntvKey), reflect.ValueOf(ntvVal))
			return true
		}
		celKey := m.NativeToValue(ntvKey)
		celVal := m.NativeToValue(ntvVal)
		ntvKey, err = celKey.ConvertToNative(otherKeyType)
		if err != nil {
			return false
		}
		ntvVal, err = celVal.ConvertToNative(otherValType)
		if err != nil {
			return false
		}
		mapVal.SetMapIndex(reflect.ValueOf(ntvKey), reflect.ValueOf(ntvVal))
		return true
	})
	if err != nil {
		return nil, err
	}
	return mapVal.Interface(), nil
}
func (m *protoMap) ConvertToType(typeVal ref.Type) ref.Val {
	switch typeVal {
	case MapType:
		return m
	case TypeType:
		return MapType
	}
	return NewErr("type conversion error from '%s' to '%s'", MapType, typeVal)
}
func (m *protoMap) Equal(other ref.Val) ref.Val {
	otherMap, ok := other.(traits.Mapper)
	if !ok {
		return MaybeNoSuchOverloadErr(other)
	}
	if m.value.Map.Len() != int(otherMap.Size().(Int)) {
		return False
	}
	var retVal ref.Val = True
	m.value.Range(func(key protoreflect.MapKey, val protoreflect.Value) bool {
		keyVal := m.NativeToValue(key.Interface())
		valVal := m.NativeToValue(val)
		otherVal, found := otherMap.Find(keyVal)
		if !found {
			if otherVal == nil {
				retVal = False
				return false
			}
			retVal = MaybeNoSuchOverloadErr(otherVal)
			return false
		}
		valEq := valVal.Equal(otherVal)
		if valEq != True {
			retVal = valEq
			return false
		}
		return true
	})
	return retVal
}
func (m *protoMap) Find(key ref.Val) (ref.Val, bool) {
	if IsUnknownOrError(key) {
		return key, false
	}
	ntvKey, err := key.ConvertToNative(m.value.KeyType.ReflectType())
	if err != nil {
		return NewErr("unsupported key type: %v", key.Type()), false
	}
	val := m.value.Get(protoreflect.ValueOf(ntvKey).MapKey())
	if !val.IsValid() {
		return nil, false
	}
	switch v := val.Interface().(type) {
	case protoreflect.List, protoreflect.Map:
		return NewErr("unsupported map element type: (%T)%v", v, v), false
	default:
		return m.NativeToValue(v), true
	}
}
func (m *protoMap) Get(key ref.Val) ref.Val {
	v, found := m.Find(key)
	if !found {
		return ValOrErr(v, "no such key: %v", key)
	}
	return v
}
func (m *protoMap) Iterator() traits.Iterator {
	mapKeys := make([]protoreflect.MapKey, 0, m.value.Len())
	m.value.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
		mapKeys = append(mapKeys, k)
		return true
	})
	return &protoMapIterator{
		TypeAdapter: m.TypeAdapter,
		mapKeys:     mapKeys,
		len:         m.value.Len(),
	}
}
func (m *protoMap) Size() ref.Val {
	return Int(m.value.Len())
}
func (m *protoMap) Type() ref.Type {
	return MapType
}
func (m *protoMap) Value() interface{} {
	return m.value
}
type mapIterator struct {
	*baseIterator
	ref.TypeAdapter
	mapKeys *reflect.MapIter
	cursor  int
	len     int
}
func (it *mapIterator) HasNext() ref.Val {
	return Bool(it.cursor < it.len)
}
func (it *mapIterator) Next() ref.Val {
	if it.HasNext() == True && it.mapKeys.Next() {
		it.cursor++
		refKey := it.mapKeys.Key()
		return it.NativeToValue(refKey.Interface())
	}
	return nil
}
type protoMapIterator struct {
	*baseIterator
	ref.TypeAdapter
	mapKeys []protoreflect.MapKey
	cursor  int
	len     int
}
func (it *protoMapIterator) HasNext() ref.Val {
	return Bool(it.cursor < it.len)
}
func (it *protoMapIterator) Next() ref.Val {
	if it.HasNext() == True {
		index := it.cursor
		it.cursor++
		refKey := it.mapKeys[index]
		return it.NativeToValue(refKey.Interface())
	}
	return nil
}
type stringKeyIterator struct {
	*baseIterator
	mapKeys []string
	cursor  int
	len     int
}
func (it *stringKeyIterator) HasNext() ref.Val {
	return Bool(it.cursor < it.len)
}