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  }