mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
6992c0b693
Also make file:pipe output a struct map rather than a pseudomap.
64 lines
1.5 KiB
Go
64 lines
1.5 KiB
Go
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(any) 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 any) 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 PseudoMap:
|
|
return hasKeyStructMap(container.Fields(), key)
|
|
default:
|
|
var found bool
|
|
err := IterateKeys(container, func(k any) 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 any) 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
|
|
}
|