2018-02-15 17:14:05 +08:00
|
|
|
package vals
|
2018-01-25 08:26:46 +08:00
|
|
|
|
2018-01-25 09:40:15 +08:00
|
|
|
import (
|
|
|
|
"errors"
|
2021-03-09 12:31:23 +08:00
|
|
|
"os"
|
2018-01-25 09:40:15 +08:00
|
|
|
)
|
2018-01-25 08:26:46 +08:00
|
|
|
|
|
|
|
// Indexer wraps the Index method.
|
|
|
|
type Indexer interface {
|
2018-03-02 07:15:51 +08:00
|
|
|
// Index retrieves the value corresponding to the specified key in the
|
|
|
|
// container. It returns the value (if any), and whether it actually exists.
|
2022-03-20 23:50:25 +08:00
|
|
|
Index(k any) (v any, ok bool)
|
2018-03-02 07:15:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// ErrIndexer wraps the Index method.
|
|
|
|
type ErrIndexer interface {
|
2018-01-25 08:26:46 +08:00
|
|
|
// Index retrieves one value from the receiver at the specified index.
|
2022-03-20 23:50:25 +08:00
|
|
|
Index(k any) (any, error)
|
2018-01-25 08:26:46 +08:00
|
|
|
}
|
|
|
|
|
2018-03-02 07:15:51 +08:00
|
|
|
var errNotIndexable = errors.New("not indexable")
|
2018-01-25 08:26:46 +08:00
|
|
|
|
2018-01-29 22:36:43 +08:00
|
|
|
type noSuchKeyError struct {
|
2022-03-20 23:50:25 +08:00
|
|
|
key any
|
2018-01-29 22:36:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NoSuchKey returns an error indicating that a key is not found in a map-like
|
|
|
|
// value.
|
2022-03-20 23:50:25 +08:00
|
|
|
func NoSuchKey(k any) error {
|
2018-01-29 22:36:43 +08:00
|
|
|
return noSuchKeyError{k}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err noSuchKeyError) Error() string {
|
2022-01-01 05:05:07 +08:00
|
|
|
return "no such key: " + ReprPlain(err.key)
|
2018-01-29 22:36:43 +08:00
|
|
|
}
|
|
|
|
|
2019-04-19 08:03:56 +08:00
|
|
|
// Index indexes a value with the given key. It is implemented for the builtin
|
2021-04-26 05:57:51 +08:00
|
|
|
// 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.
|
2022-03-20 23:50:25 +08:00
|
|
|
func Index(a, k any) (any, error) {
|
2023-07-15 06:45:25 +08:00
|
|
|
convertResult := func(v any, ok bool) (any, error) {
|
|
|
|
if !ok {
|
|
|
|
return nil, NoSuchKey(k)
|
|
|
|
}
|
|
|
|
return v, nil
|
|
|
|
}
|
2018-01-25 08:26:46 +08:00
|
|
|
switch a := a.(type) {
|
2019-04-19 08:03:56 +08:00
|
|
|
case string:
|
|
|
|
return indexString(a, k)
|
2021-03-09 12:31:23 +08:00
|
|
|
case *os.File:
|
2021-04-26 05:57:51 +08:00
|
|
|
return indexFile(a, k)
|
2018-03-02 07:15:51 +08:00
|
|
|
case ErrIndexer:
|
2018-02-02 12:42:41 +08:00
|
|
|
return a.Index(k)
|
2018-03-02 07:15:51 +08:00
|
|
|
case Indexer:
|
2023-07-15 06:45:25 +08:00
|
|
|
return convertResult(a.Index(k))
|
2020-06-28 08:47:31 +08:00
|
|
|
case List:
|
|
|
|
return indexList(a, k)
|
|
|
|
case StructMap:
|
2023-07-15 06:45:25 +08:00
|
|
|
return convertResult(indexStructMap(a, k))
|
2023-07-18 01:53:01 +08:00
|
|
|
case PseudoMap:
|
2023-07-15 06:45:25 +08:00
|
|
|
return convertResult(indexStructMap(a.Fields(), k))
|
2018-01-25 08:26:46 +08:00
|
|
|
default:
|
|
|
|
return nil, errNotIndexable
|
|
|
|
}
|
|
|
|
}
|
2019-04-20 00:40:45 +08:00
|
|
|
|
2022-03-20 23:50:25 +08:00
|
|
|
func indexFile(f *os.File, k any) (any, error) {
|
2021-04-26 05:57:51 +08:00
|
|
|
switch k {
|
|
|
|
case "fd":
|
|
|
|
return int(f.Fd()), nil
|
|
|
|
case "name":
|
|
|
|
return f.Name(), nil
|
|
|
|
}
|
|
|
|
return nil, NoSuchKey(k)
|
|
|
|
}
|
|
|
|
|
2023-07-15 06:45:25 +08:00
|
|
|
func indexStructMap(a StructMap, k any) (any, bool) {
|
2020-06-29 07:22:36 +08:00
|
|
|
fieldName, ok := k.(string)
|
|
|
|
if !ok || fieldName == "" {
|
2023-07-15 06:45:25 +08:00
|
|
|
return nil, false
|
2020-06-29 07:22:36 +08:00
|
|
|
}
|
2023-07-15 06:45:25 +08:00
|
|
|
for it := iterateStructMap(a); it.HasElem(); it.Next() {
|
|
|
|
k, v := it.elem()
|
2019-04-20 00:40:45 +08:00
|
|
|
if k == fieldName {
|
2023-07-15 06:45:25 +08:00
|
|
|
return FromGo(v), true
|
2019-04-20 00:40:45 +08:00
|
|
|
}
|
|
|
|
}
|
2023-07-15 06:45:25 +08:00
|
|
|
return nil, false
|
2019-04-20 00:40:45 +08:00
|
|
|
}
|