github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/core/elvish/eval/vals/index.go (about) 1 package vals 2 3 import ( 4 "errors" 5 ) 6 7 // Indexer wraps the Index method. 8 type Indexer interface { 9 // Index retrieves the value corresponding to the specified key in the 10 // container. It returns the value (if any), and whether it actually exists. 11 Index(k interface{}) (v interface{}, ok bool) 12 } 13 14 // ErrIndexer wraps the Index method. 15 type ErrIndexer interface { 16 // Index retrieves one value from the receiver at the specified index. 17 Index(k interface{}) (interface{}, error) 18 } 19 20 var errNotIndexable = errors.New("not indexable") 21 22 type noSuchKeyError struct { 23 key interface{} 24 } 25 26 // NoSuchKey returns an error indicating that a key is not found in a map-like 27 // value. 28 func NoSuchKey(k interface{}) error { 29 return noSuchKeyError{k} 30 } 31 32 func (err noSuchKeyError) Error() string { 33 return "no such key: " + Repr(err.key, NoPretty) 34 } 35 36 // Index indexes a value with the given key. It is implemented for types 37 // satisfying the ErrIndexer or Indexer interface, types satisfying the 38 // listIndexable interface (which covers Vector), and the builtin string type. 39 // For other types, it returns a nil value and a non-nil error. 40 func Index(a, k interface{}) (interface{}, error) { 41 switch a := a.(type) { 42 case ErrIndexer: 43 return a.Index(k) 44 case Indexer: 45 v, ok := a.Index(k) 46 if !ok { 47 return nil, NoSuchKey(k) 48 } 49 return v, nil 50 case listIndexable: 51 return indexList(a, k) 52 case string: 53 return indexString(a, k) 54 default: 55 return nil, errNotIndexable 56 } 57 }