github.com/mem/u-root@v2.0.1-0.20181004165302-9b18b4636a33+incompatible/cmds/elvish/eval/vals/assoc.go (about) 1 package vals 2 3 import ( 4 "errors" 5 6 "github.com/xiaq/persistent/vector" 7 ) 8 9 // Assocer wraps the Assoc method. 10 type Assocer interface { 11 // Assoc returns a slightly modified version of the receiver with key k 12 // associated with value v. 13 Assoc(k, v interface{}) (interface{}, error) 14 } 15 16 var ( 17 errAssocUnsupported = errors.New("assoc is not supported") 18 errReplacementMustBeString = errors.New("replacement must be string") 19 errAssocWithSlice = errors.New("assoc with slice not yet supported") 20 ) 21 22 // Assoc takes a container, a key and value, and returns a modified version of 23 // the container, in which the key associated with the value. It is implemented 24 // for the builtin type string, and types satisfying the listAssocable, 25 // mapAssocable or Assocer interface. For other types, it returns an error. 26 func Assoc(a, k, v interface{}) (interface{}, error) { 27 switch a := a.(type) { 28 case Assocer: 29 return a.Assoc(k, v) 30 case string: 31 return assocString(a, k, v) 32 case listAssocable: 33 return assocList(a, k, v) 34 case mapAssocable: 35 return a.Assoc(k, v), nil 36 } 37 return nil, errAssocUnsupported 38 } 39 40 func assocString(s string, k, v interface{}) (interface{}, error) { 41 i, j, err := convertStringIndex(k, s) 42 if err != nil { 43 return nil, err 44 } 45 repl, ok := v.(string) 46 if !ok { 47 return nil, errReplacementMustBeString 48 } 49 return s[:i] + repl + s[j:], nil 50 } 51 52 type listAssocable interface { 53 Lener 54 Assoc(int, interface{}) vector.Vector 55 } 56 57 var _ listAssocable = vector.Vector(nil) 58 59 func assocList(l listAssocable, k, v interface{}) (interface{}, error) { 60 kstring, ok := k.(string) 61 if !ok { 62 return nil, errIndexMustBeString 63 } 64 index, err := ConvertListIndex(kstring, l.Len()) 65 if err != nil { 66 return nil, err 67 } 68 if index.Slice { 69 return nil, errAssocWithSlice 70 } 71 return l.Assoc(index.Lower, v), nil 72 }