2018-02-15 17:14:05 +08:00
|
|
|
package vals
|
2018-01-25 08:26:46 +08:00
|
|
|
|
2018-01-28 01:26:22 +08:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
)
|
2018-01-25 08:26:46 +08:00
|
|
|
|
|
|
|
// Assocer wraps the Assoc method.
|
|
|
|
type Assocer interface {
|
|
|
|
// Assoc returns a slightly modified version of the receiver with key k
|
|
|
|
// associated with value v.
|
2022-03-20 23:50:25 +08:00
|
|
|
Assoc(k, v any) (any, error)
|
2018-01-25 08:26:46 +08:00
|
|
|
}
|
|
|
|
|
2018-01-28 01:26:22 +08:00
|
|
|
var (
|
2018-02-01 00:36:01 +08:00
|
|
|
errAssocUnsupported = errors.New("assoc is not supported")
|
|
|
|
errReplacementMustBeString = errors.New("replacement must be string")
|
|
|
|
errAssocWithSlice = errors.New("assoc with slice not yet supported")
|
2018-01-28 01:26:22 +08:00
|
|
|
)
|
2018-01-25 08:26:46 +08:00
|
|
|
|
2018-01-28 01:26:22 +08:00
|
|
|
// Assoc takes a container, a key and value, and returns a modified version of
|
|
|
|
// the container, in which the key associated with the value. It is implemented
|
2019-04-20 00:40:45 +08:00
|
|
|
// for the builtin type string, List and Map types, StructMap types, and types
|
|
|
|
// satisfying the Assocer interface. For other types, it returns an error.
|
2022-03-20 23:50:25 +08:00
|
|
|
func Assoc(a, k, v any) (any, error) {
|
2018-01-25 08:26:46 +08:00
|
|
|
switch a := a.(type) {
|
2018-01-25 09:40:15 +08:00
|
|
|
case string:
|
2018-01-28 01:26:22 +08:00
|
|
|
return assocString(a, k, v)
|
2019-04-19 19:24:45 +08:00
|
|
|
case List:
|
2018-01-28 01:26:22 +08:00
|
|
|
return assocList(a, k, v)
|
2019-04-19 19:24:45 +08:00
|
|
|
case Map:
|
2018-01-29 22:36:43 +08:00
|
|
|
return a.Assoc(k, v), nil
|
2023-07-15 06:45:25 +08:00
|
|
|
case StructMap:
|
|
|
|
return promoteToMap(a).Assoc(k, v), nil
|
2019-04-19 08:03:56 +08:00
|
|
|
case Assocer:
|
|
|
|
return a.Assoc(k, v)
|
2018-01-25 08:26:46 +08:00
|
|
|
}
|
|
|
|
return nil, errAssocUnsupported
|
|
|
|
}
|
2018-01-25 09:40:15 +08:00
|
|
|
|
2022-03-20 23:50:25 +08:00
|
|
|
func assocString(s string, k, v any) (any, error) {
|
2018-01-28 01:26:22 +08:00
|
|
|
i, j, err := convertStringIndex(k, s)
|
2018-01-25 09:40:15 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
repl, ok := v.(string)
|
|
|
|
if !ok {
|
2018-01-28 01:26:22 +08:00
|
|
|
return nil, errReplacementMustBeString
|
2018-01-25 09:40:15 +08:00
|
|
|
}
|
|
|
|
return s[:i] + repl + s[j:], nil
|
|
|
|
}
|
2018-01-28 01:26:22 +08:00
|
|
|
|
2022-03-20 23:50:25 +08:00
|
|
|
func assocList(l List, k, v any) (any, error) {
|
2019-04-28 04:00:25 +08:00
|
|
|
index, err := ConvertListIndex(k, l.Len())
|
2018-01-28 01:26:22 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if index.Slice {
|
|
|
|
return nil, errAssocWithSlice
|
|
|
|
}
|
2018-03-02 07:15:51 +08:00
|
|
|
return l.Assoc(index.Lower, v), nil
|
2018-01-28 01:26:22 +08:00
|
|
|
}
|