mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
bd8130ee07
See code comment for details.
56 lines
1.4 KiB
Go
56 lines
1.4 KiB
Go
package vals
|
|
|
|
import (
|
|
"reflect"
|
|
)
|
|
|
|
// KeysIterator wraps the IterateKeys method.
|
|
type KeysIterator interface {
|
|
// IterateKeys calls the passed function with each key within the receiver.
|
|
// The iteration is aborted if the function returns false.
|
|
IterateKeys(func(v interface{}) bool)
|
|
}
|
|
|
|
type cannotIterateKeysOf struct{ kind string }
|
|
|
|
func (err cannotIterateKeysOf) Error() string {
|
|
return "cannot iterate keys of " + err.kind
|
|
}
|
|
|
|
// IterateKeys iterates the keys of the supplied value, calling the supplied
|
|
// function for each key. The function can return false to break the iteration.
|
|
// It is implemented for the Map type, StructMap types, and types satisfying the
|
|
// IterateKeyser interface. For these types, it always returns a nil error. For
|
|
// other types, it doesn't do anything and returns an error.
|
|
func IterateKeys(v interface{}, f func(interface{}) bool) error {
|
|
switch v := v.(type) {
|
|
case KeysIterator:
|
|
v.IterateKeys(f)
|
|
case Map:
|
|
for it := v.Iterator(); it.HasElem(); it.Next() {
|
|
k, _ := it.Elem()
|
|
if !f(k) {
|
|
break
|
|
}
|
|
}
|
|
case StructMap:
|
|
iterateKeysStructMap(v, f)
|
|
case PseudoStructMap:
|
|
iterateKeysStructMap(v.Fields(), f)
|
|
default:
|
|
return cannotIterateKeysOf{Kind(v)}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func iterateKeysStructMap(v StructMap, f func(interface{}) bool) {
|
|
for _, k := range getStructMapInfo(reflect.TypeOf(v)).fieldNames {
|
|
if k == "" {
|
|
continue
|
|
}
|
|
if !f(k) {
|
|
break
|
|
}
|
|
}
|
|
}
|