diff --git a/.changelog/aac5dad3483948a690606460eeb1e8d2.json b/.changelog/aac5dad3483948a690606460eeb1e8d2.json new file mode 100644 index 00000000000..56a3ec7ee62 --- /dev/null +++ b/.changelog/aac5dad3483948a690606460eeb1e8d2.json @@ -0,0 +1,8 @@ +{ + "id": "aac5dad3-4839-48a6-9060-6460eeb1e8d2", + "type": "dependency", + "description": "Remove unused go-jmespath dependency from main module.", + "modules": [ + "." + ] +} \ No newline at end of file diff --git a/go.mod b/go.mod index ed9bdfdfc38..5f67886570c 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,5 @@ module github.com/aws/aws-sdk-go-v2 -require ( - github.com/aws/smithy-go v1.20.3 - github.com/jmespath/go-jmespath v0.4.0 -) +require github.com/aws/smithy-go v1.20.3 go 1.20 diff --git a/go.sum b/go.sum index eb1604bcdab..07970476de0 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,2 @@ github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE= github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/awsutil/path_value.go b/internal/awsutil/path_value.go deleted file mode 100644 index 58ef438a196..00000000000 --- a/internal/awsutil/path_value.go +++ /dev/null @@ -1,225 +0,0 @@ -package awsutil - -import ( - "reflect" - "regexp" - "strconv" - "strings" - - "github.com/jmespath/go-jmespath" -) - -var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`) - -// rValuesAtPath returns a slice of values found in value v. The values -// in v are explored recursively so all nested values are collected. -func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value { - pathparts := strings.Split(path, "||") - if len(pathparts) > 1 { - for _, pathpart := range pathparts { - vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm) - if len(vals) > 0 { - return vals - } - } - return nil - } - - values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))} - components := strings.Split(path, ".") - for len(values) > 0 && len(components) > 0 { - var index *int64 - var indexStar bool - c := strings.TrimSpace(components[0]) - if c == "" { // no actual component, illegal syntax - return nil - } else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] { - // TODO normalize case for user - return nil // don't support unexported fields - } - - // parse this component - if m := indexRe.FindStringSubmatch(c); m != nil { - c = m[1] - if m[2] == "" { - index = nil - indexStar = true - } else { - i, _ := strconv.ParseInt(m[2], 10, 32) - index = &i - indexStar = false - } - } - - nextvals := []reflect.Value{} - for _, value := range values { - // pull component name out of struct member - if value.Kind() != reflect.Struct { - continue - } - - if c == "*" { // pull all members - for i := 0; i < value.NumField(); i++ { - if f := reflect.Indirect(value.Field(i)); f.IsValid() { - nextvals = append(nextvals, f) - } - } - continue - } - - value = value.FieldByNameFunc(func(name string) bool { - if c == name { - return true - } else if !caseSensitive && strings.EqualFold(name, c) { - return true - } - return false - }) - - if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 { - if !value.IsNil() { - value.Set(reflect.Zero(value.Type())) - } - return []reflect.Value{value} - } - - if createPath && value.Kind() == reflect.Ptr && value.IsNil() { - // TODO if the value is the terminus it should not be created - // if the value to be set to its position is nil. - value.Set(reflect.New(value.Type().Elem())) - value = value.Elem() - } else { - value = reflect.Indirect(value) - } - - if value.Kind() == reflect.Slice || value.Kind() == reflect.Map { - if !createPath && value.IsNil() { - value = reflect.ValueOf(nil) - } - } - - if value.IsValid() { - nextvals = append(nextvals, value) - } - } - values = nextvals - - if indexStar || index != nil { - nextvals = []reflect.Value{} - for _, valItem := range values { - value := reflect.Indirect(valItem) - if value.Kind() != reflect.Slice { - continue - } - - if indexStar { // grab all indices - for i := 0; i < value.Len(); i++ { - idx := reflect.Indirect(value.Index(i)) - if idx.IsValid() { - nextvals = append(nextvals, idx) - } - } - continue - } - - // pull out index - i := int(*index) - if i >= value.Len() { // check out of bounds - if createPath { - // TODO resize slice - } else { - continue - } - } else if i < 0 { // support negative indexing - i = value.Len() + i - } - value = reflect.Indirect(value.Index(i)) - - if value.Kind() == reflect.Slice || value.Kind() == reflect.Map { - if !createPath && value.IsNil() { - value = reflect.ValueOf(nil) - } - } - - if value.IsValid() { - nextvals = append(nextvals, value) - } - } - values = nextvals - } - - components = components[1:] - } - return values -} - -// ValuesAtPath returns a list of values at the case insensitive lexical -// path inside of a structure. -func ValuesAtPath(i interface{}, path string) ([]interface{}, error) { - result, err := jmespath.Search(path, i) - if err != nil { - return nil, err - } - - v := reflect.ValueOf(result) - if !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) { - return nil, nil - } - if s, ok := result.([]interface{}); ok { - return s, err - } - if v.Kind() == reflect.Map && v.Len() == 0 { - return nil, nil - } - if v.Kind() == reflect.Slice { - out := make([]interface{}, v.Len()) - for i := 0; i < v.Len(); i++ { - out[i] = v.Index(i).Interface() - } - return out, nil - } - - return []interface{}{result}, nil -} - -// SetValueAtPath sets a value at the case insensitive lexical path inside -// of a structure. -func SetValueAtPath(i interface{}, path string, v interface{}) { - if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil { - for _, rval := range rvals { - if rval.Kind() == reflect.Ptr && rval.IsNil() { - continue - } - setValue(rval, v) - } - } -} - -func setValue(dstVal reflect.Value, src interface{}) { - if dstVal.Kind() == reflect.Ptr { - dstVal = reflect.Indirect(dstVal) - } - srcVal := reflect.ValueOf(src) - - if !srcVal.IsValid() { // src is literal nil - if dstVal.CanAddr() { - // Convert to pointer so that pointer's value can be nil'ed - // dstVal = dstVal.Addr() - } - dstVal.Set(reflect.Zero(dstVal.Type())) - - } else if srcVal.Kind() == reflect.Ptr { - if srcVal.IsNil() { - srcVal = reflect.Zero(dstVal.Type()) - } else { - srcVal = reflect.ValueOf(src).Elem() - } - dstVal.Set(srcVal) - } else { - if dstVal.Kind() == reflect.String { - dstVal.SetString(srcVal.String()) - } else { - dstVal.Set(srcVal) - } - } -} diff --git a/internal/awsutil/path_value_test.go b/internal/awsutil/path_value_test.go deleted file mode 100644 index d44019ac52b..00000000000 --- a/internal/awsutil/path_value_test.go +++ /dev/null @@ -1,182 +0,0 @@ -package awsutil_test - -import ( - "strings" - "testing" - - "github.com/aws/aws-sdk-go-v2/internal/awsutil" -) - -type Struct struct { - A []Struct - z []Struct - B *Struct - D *Struct - C string - E map[string]string -} - -var data = Struct{ - A: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}}, - z: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}}, - B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}}, - C: "initial", -} -var data2 = Struct{A: []Struct{ - {A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}}, - {A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}}, -}} - -func TestValueAtPathSuccess(t *testing.T) { - var testCases = []struct { - expect []interface{} - data interface{} - path string - }{ - {[]interface{}{"initial"}, data, "C"}, - {[]interface{}{"value1"}, data, "A[0].C"}, - {[]interface{}{"value2"}, data, "A[1].C"}, - {[]interface{}{"value3"}, data, "A[2].C"}, - {[]interface{}{"value3"}, data, "a[2].c"}, - {[]interface{}{"value3"}, data, "A[-1].C"}, - {[]interface{}{"value1", "value2", "value3"}, data, "A[].C"}, - {[]interface{}{"terminal"}, data, "B . B . C"}, - {[]interface{}{"initial"}, data, "A.D.X || C"}, - {[]interface{}{"initial"}, data, "A[0].B || C"}, - {[]interface{}{ - Struct{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}}, - Struct{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}}, - }, data2, "A"}, - } - for i, c := range testCases { - v, err := awsutil.ValuesAtPath(c.data, c.path) - if err != nil { - t.Errorf("case %v, expected no error, %v", i, c.path) - } - if e, a := c.expect, v; !awsutil.DeepEqual(e, a) { - t.Errorf("case %v, %v", i, c.path) - } - } -} - -func TestValueAtPathFailure(t *testing.T) { - var testCases = []struct { - expect []interface{} - errContains string - data interface{} - path string - }{ - {nil, "", data, "C.x"}, - {nil, "SyntaxError: Invalid token: tDot", data, ".x"}, - {nil, "", data, "X.Y.Z"}, - {nil, "", data, "A[100].C"}, - {nil, "", data, "A[3].C"}, - {nil, "", data, "B.B.C.Z"}, - {nil, "", data, "z[-1].C"}, - {nil, "", nil, "A.B.C"}, - {[]interface{}{}, "", Struct{}, "A"}, - {nil, "", data, "A[0].B.C"}, - {nil, "", data, "D"}, - } - - for i, c := range testCases { - v, err := awsutil.ValuesAtPath(c.data, c.path) - if c.errContains != "" { - if !strings.Contains(err.Error(), c.errContains) { - t.Errorf("case %v, expected error, %v", i, c.path) - } - continue - } else { - if err != nil { - t.Errorf("case %v, expected no error, %v", i, c.path) - } - } - if e, a := c.expect, v; !awsutil.DeepEqual(e, a) { - t.Errorf("case %v, %v", i, c.path) - } - } -} - -func TestSetValueAtPathSuccess(t *testing.T) { - var s Struct - awsutil.SetValueAtPath(&s, "C", "test1") - awsutil.SetValueAtPath(&s, "B.B.C", "test2") - awsutil.SetValueAtPath(&s, "B.D.C", "test3") - if e, a := "test1", s.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - if e, a := "test2", s.B.B.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - if e, a := "test3", s.B.D.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - awsutil.SetValueAtPath(&s, "B.*.C", "test0") - if e, a := "test0", s.B.B.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - if e, a := "test0", s.B.D.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - var s2 Struct - awsutil.SetValueAtPath(&s2, "b.b.c", "test0") - if e, a := "test0", s2.B.B.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - awsutil.SetValueAtPath(&s2, "A", []Struct{{}}) - if e, a := []Struct{{}}, s2.A; !awsutil.DeepEqual(e, a) { - t.Errorf("expected %v, but received %v", e, a) - } - - str := "foo" - - s3 := Struct{} - awsutil.SetValueAtPath(&s3, "b.b.c", str) - if e, a := "foo", s3.B.B.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - s3 = Struct{B: &Struct{B: &Struct{C: str}}} - awsutil.SetValueAtPath(&s3, "b.b.c", nil) - if e, a := "", s3.B.B.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - s3 = Struct{} - awsutil.SetValueAtPath(&s3, "b.b.c", nil) - if e, a := "", s3.B.B.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - s3 = Struct{} - awsutil.SetValueAtPath(&s3, "b.b.c", &str) - if e, a := "foo", s3.B.B.C; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - var s4 struct{ Name *string } - awsutil.SetValueAtPath(&s4, "Name", str) - if e, a := str, *s4.Name; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - s4 = struct{ Name *string }{} - awsutil.SetValueAtPath(&s4, "Name", nil) - if e, a := (*string)(nil), s4.Name; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - s4 = struct{ Name *string }{Name: &str} - awsutil.SetValueAtPath(&s4, "Name", nil) - if e, a := (*string)(nil), s4.Name; e != a { - t.Errorf("expected %v, but received %v", e, a) - } - - s4 = struct{ Name *string }{} - awsutil.SetValueAtPath(&s4, "Name", &str) - if e, a := str, *s4.Name; e != a { - t.Errorf("expected %v, but received %v", e, a) - } -}