3
0

Allow appending to KVV values (kvv.field[] = val)

This commit is contained in:
Denis Arh 2021-08-16 21:46:58 +02:00
parent 0b7e9b108b
commit 14b3f07941
4 changed files with 59 additions and 7 deletions

View File

@ -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())

View File

@ -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()},
}

View File

@ -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) {

View File

@ -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) {