package vals

import (
	
	
	
)

// Indexer wraps the Index method.
type Indexer interface {
	// Index retrieves the value corresponding to the specified key in the
	// container. It returns the value (if any), and whether it actually exists.
	Index(k interface{}) (v interface{}, ok bool)
}

// ErrIndexer wraps the Index method.
type ErrIndexer interface {
	// Index retrieves one value from the receiver at the specified index.
	Index(k interface{}) (interface{}, error)
}

var errNotIndexable = errors.New("not indexable")

type noSuchKeyError struct {
	key interface{}
}

// NoSuchKey returns an error indicating that a key is not found in a map-like
// value.
func ( interface{}) error {
	return noSuchKeyError{}
}

func ( noSuchKeyError) () string {
	return "no such key: " + Repr(.key, NoPretty)
}

// Index indexes a value with the given key. It is implemented for the builtin
// type string, *os.File, List, StructMap and PseudoStructMap types, and types
// satisfying the ErrIndexer or Indexer interface (the Map type satisfies
// Indexer). For other types, it returns a nil value and a non-nil error.
func (,  interface{}) (interface{}, error) {
	switch a := .(type) {
	case string:
		return indexString(, )
	case *os.File:
		return indexFile(, )
	case ErrIndexer:
		return .Index()
	case Indexer:
		,  := .Index()
		if ! {
			return nil, NoSuchKey()
		}
		return , nil
	case List:
		return indexList(, )
	case StructMap:
		return indexStructMap(, )
	case PseudoStructMap:
		return indexStructMap(.Fields(), )
	default:
		return nil, errNotIndexable
	}
}

func ( *os.File,  interface{}) (interface{}, error) {
	switch  {
	case "fd":
		return int(.Fd()), nil
	case "name":
		return .Name(), nil
	}
	return nil, NoSuchKey()
}

func ( StructMap,  interface{}) (interface{}, error) {
	,  := .(string)
	if ! ||  == "" {
		return nil, NoSuchKey()
	}
	 := reflect.ValueOf()
	 := iterateStructMap(reflect.TypeOf())
	for .Next() {
		,  := .Get()
		if  ==  {
			return FromGo(), nil
		}
	}
	return nil, NoSuchKey()
}