github.com/elves/elvish@v0.15.0/pkg/eval/vals/iterate_keys.go (about) 1 package vals 2 3 import ( 4 "reflect" 5 ) 6 7 // KeysIterator wraps the IterateKeys method. 8 type KeysIterator interface { 9 // IterateKeys calls the passed function with each key within the receiver. 10 // The iteration is aborted if the function returns false. 11 IterateKeys(func(v interface{}) bool) 12 } 13 14 type cannotIterateKeysOf struct{ kind string } 15 16 func (err cannotIterateKeysOf) Error() string { 17 return "cannot iterate keys of " + err.kind 18 } 19 20 // IterateKeys iterates the keys of the supplied value, calling the supplied 21 // function for each key. The function can return false to break the iteration. 22 // It is implemented for the Map type, StructMap types, and types satisfying the 23 // IterateKeyser interface. For these types, it always returns a nil error. For 24 // other types, it doesn't do anything and returns an error. 25 func IterateKeys(v interface{}, f func(interface{}) bool) error { 26 switch v := v.(type) { 27 case KeysIterator: 28 v.IterateKeys(f) 29 case Map: 30 for it := v.Iterator(); it.HasElem(); it.Next() { 31 k, _ := it.Elem() 32 if !f(k) { 33 break 34 } 35 } 36 case StructMap: 37 iterateKeysStructMap(v, f) 38 case PseudoStructMap: 39 iterateKeysStructMap(v.Fields(), f) 40 default: 41 return cannotIterateKeysOf{Kind(v)} 42 } 43 return nil 44 } 45 46 func iterateKeysStructMap(v StructMap, f func(interface{}) bool) { 47 for _, k := range getStructMapInfo(reflect.TypeOf(v)).fieldNames { 48 if k == "" { 49 continue 50 } 51 if !f(k) { 52 break 53 } 54 } 55 }