package vals import ( "reflect" "src.elv.sh/pkg/persistent/hashmap" ) // HasKeyer wraps the HasKey method. type HasKeyer interface { // HasKey returns whether the receiver has the given argument as a valid // key. HasKey(interface{}) bool } // HasKey returns whether a container has a key. It is implemented for the Map // type, StructMap types, and types satisfying the HasKeyer interface. It falls // back to iterating keys using IterateKeys, and if that fails, it falls back to // calling Len and checking if key is a valid numeric or slice index. Otherwise // it returns false. func HasKey(container, key interface{}) bool { switch container := container.(type) { case HasKeyer: return container.HasKey(key) case Map: return hashmap.HasKey(container, key) case StructMap: return hasKeyStructMap(container, key) case PseudoStructMap: return hasKeyStructMap(container.Fields(), key) default: var found bool err := IterateKeys(container, func(k interface{}) bool { if key == k { found = true } return !found }) if err == nil { return found } if len := Len(container); len >= 0 { // TODO(xiaq): Not all types that implement Lener have numerical // indices _, err := ConvertListIndex(key, len) return err == nil } return false } } func hasKeyStructMap(m StructMap, k interface{}) bool { kstring, ok := k.(string) if !ok || kstring == "" { return false } for _, fieldName := range getStructMapInfo(reflect.TypeOf(m)).fieldNames { if fieldName == kstring { return true } } return false }