Allow appending to KVV values (kvv.field[] = val)
This commit is contained in:
parent
0b7e9b108b
commit
14b3f07941
@ -20,7 +20,8 @@ func PathSplit(path string) ([]string, error) {
|
||||
s.Split(pathSplitter)
|
||||
|
||||
for s.Scan() {
|
||||
if len(s.Text()) == 0 {
|
||||
// checks if two consecutive path parts are empty
|
||||
if len(s.Text()) == 0 && len(out) > 0 && len(out[len(out)-1]) == 0 {
|
||||
return nil, invalidPathErr
|
||||
}
|
||||
out = append(out, s.Text())
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPathSplit(t *testing.T) {
|
||||
@ -16,6 +17,7 @@ func TestPathSplit(t *testing.T) {
|
||||
{p: "a.b[1]", r: []string{"a", "b", "1"}},
|
||||
{p: "a.b[1].baz[0]", r: []string{"a", "b", "1", "baz", "0"}},
|
||||
{p: "a.[]", err: invalidPathErr.Error()},
|
||||
{p: "a[]", r: []string{"a", ""}},
|
||||
{p: "a[1]bzz", err: invalidPathErr.Error()},
|
||||
}
|
||||
|
||||
|
||||
@ -540,18 +540,56 @@ func (t *KV) Delete(keys ...string) (out TypedValue, err error) {
|
||||
return kv, nil
|
||||
}
|
||||
|
||||
func (t *KVV) AssignFieldValue(key string, val TypedValue) error {
|
||||
func (t *KVV) AssignFieldValue(key []string, val TypedValue) error {
|
||||
return assignToKVV(t, key, val)
|
||||
}
|
||||
|
||||
func assignToKVV(t *KVV, key string, val TypedValue) error {
|
||||
func assignToKVV(t *KVV, kk []string, val TypedValue) error {
|
||||
if t.value == nil {
|
||||
t.value = make(map[string][]string)
|
||||
}
|
||||
|
||||
str, err := cast.ToStringSliceE(val.Get())
|
||||
t.value[key] = str
|
||||
return err
|
||||
switch len(kk) {
|
||||
case 2:
|
||||
str, err := cast.ToStringE(val.Get())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key, ind := kk[0], kk[1]
|
||||
|
||||
if len(ind) > 0 {
|
||||
// handles kvv.field[42] = "value"
|
||||
index, err := cast.ToIntE(ind)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if index >= 0 && index < len(t.value[key]) {
|
||||
// handles positive & in-range indexes
|
||||
t.value[key][index] = str
|
||||
return nil
|
||||
}
|
||||
|
||||
//negative & out-of-range indexes are always appended
|
||||
}
|
||||
|
||||
// handles kvv.field[] = "value"
|
||||
t.value[key] = append(t.value[key], str)
|
||||
|
||||
case 1:
|
||||
str, err := cast.ToStringSliceE(val.Get())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t.value[kk[0]] = str
|
||||
|
||||
default:
|
||||
return fmt.Errorf("cannot set value on %s with path '%s'", t.Type(), strings.Join(kk, "."))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CastToKVV(val interface{}) (out map[string][]string, err error) {
|
||||
|
||||
@ -362,6 +362,17 @@ func TestKVV_Assign(t *testing.T) {
|
||||
req.NoError(kvv.Assign(url.Values{"foo": []string{"bar"}}))
|
||||
req.Contains(kvv.value, "foo")
|
||||
req.Equal([]string{"bar"}, kvv.value["foo"])
|
||||
|
||||
kvv = KVV{}
|
||||
req.NoError(Assign(&kvv, "deep", Must(NewString("bar"))))
|
||||
req.NoError(Assign(&kvv, "deep[0]", Must(NewString("bar"))))
|
||||
req.NoError(Assign(&kvv, "deep[]", Must(NewString("baz"))))
|
||||
req.NoError(Assign(&kvv, "deep[]", Must(NewString("bar"))))
|
||||
req.NoError(Assign(&kvv, "deep[3]", Must(NewString("baz"))))
|
||||
req.NoError(Assign(&kvv, "deep[3]", Must(NewString("b4z"))))
|
||||
req.Contains(kvv.value, "deep")
|
||||
req.Equal([]string{"bar", "baz", "bar", "b4z"}, kvv.value["deep"])
|
||||
|
||||
}
|
||||
|
||||
func TestKVV_Set(t *testing.T) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user