From 78c7b186fde1e9b292bbd0fc4fd8fb15300ea2ca Mon Sep 17 00:00:00 2001 From: Anatoly Rugalev Date: Tue, 12 Nov 2024 13:21:45 +0100 Subject: [PATCH 1/6] fix(dynamodb): fix StringSet, NumberSet and BinarySet decoding --- feature/dynamodb/attributevalue/decode.go | 18 +++++++++++--- .../dynamodb/attributevalue/shared_test.go | 24 +++++++++++++++++++ .../dynamodbstreams/attributevalue/decode.go | 18 +++++++++++--- .../attributevalue/shared_test.go | 24 +++++++++++++++++++ 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/feature/dynamodb/attributevalue/decode.go b/feature/dynamodb/attributevalue/decode.go index 15a94f4b24d..a0695646e94 100644 --- a/feature/dynamodb/attributevalue/decode.go +++ b/feature/dynamodb/attributevalue/decode.go @@ -447,7 +447,11 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - return u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberBS{Value: bs}) + err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) + if err != nil { + return err + } + continue } if err := d.decodeBinary(bs[i], elem); err != nil { return err @@ -582,7 +586,11 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - return u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberNS{Value: ns}) + err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) + if err != nil { + return err + } + continue } if err := d.decodeNumber(ns[i], elem, tag{}); err != nil { return err @@ -804,7 +812,11 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - return u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberSS{Value: ss}) + err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) + if err != nil { + return err + } + continue } if err := d.decodeString(ss[i], elem, tag{}); err != nil { return err diff --git a/feature/dynamodb/attributevalue/shared_test.go b/feature/dynamodb/attributevalue/shared_test.go index 67a1791da50..0eb1e643461 100644 --- a/feature/dynamodb/attributevalue/shared_test.go +++ b/feature/dynamodb/attributevalue/shared_test.go @@ -38,6 +38,21 @@ type testStringSetStruct struct { Strings []string `dynamodbav:",stringset"` } +type testStringItem string + +func (t *testStringItem) UnmarshalDynamoDBAttributeValue(av types.AttributeValue) error { + v, ok := av.(*types.AttributeValueMemberS) + if !ok { + return fmt.Errorf("expecting string value") + } + *t = testStringItem(v.Value) + return nil +} + +type testStringSetWithUnmarshaler struct { + Items []testStringItem `dynamodbav:",stringset"` +} + type testIntAsStringStruct struct { Value int `dynamodbav:",string"` } @@ -201,6 +216,15 @@ var sharedTestCases = map[string]struct { actual: &testStringSetStruct{}, expected: testStringSetStruct{Strings: []string{"abc", "efg"}}, }, + "string Set with Unmarshaler": { + in: &types.AttributeValueMemberM{ + Value: map[string]types.AttributeValue{ + "Items": &types.AttributeValueMemberSS{Value: []string{"abc", "efg"}}, + }, + }, + actual: &testStringSetWithUnmarshaler{}, + expected: testStringSetWithUnmarshaler{Items: []testStringItem{"abc", "efg"}}, + }, "int value as string": { in: &types.AttributeValueMemberM{ Value: map[string]types.AttributeValue{ diff --git a/feature/dynamodbstreams/attributevalue/decode.go b/feature/dynamodbstreams/attributevalue/decode.go index 35021869967..60e0fdb08ea 100644 --- a/feature/dynamodbstreams/attributevalue/decode.go +++ b/feature/dynamodbstreams/attributevalue/decode.go @@ -447,7 +447,11 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - return u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberBS{Value: bs}) + err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) + if err != nil { + return err + } + continue } if err := d.decodeBinary(bs[i], elem); err != nil { return err @@ -582,7 +586,11 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - return u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberNS{Value: ns}) + err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) + if err != nil { + return err + } + continue } if err := d.decodeNumber(ns[i], elem, tag{}); err != nil { return err @@ -804,7 +812,11 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - return u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberSS{Value: ss}) + err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) + if err != nil { + return err + } + continue } if err := d.decodeString(ss[i], elem, tag{}); err != nil { return err diff --git a/feature/dynamodbstreams/attributevalue/shared_test.go b/feature/dynamodbstreams/attributevalue/shared_test.go index 3a3721db420..17f0514f4e4 100644 --- a/feature/dynamodbstreams/attributevalue/shared_test.go +++ b/feature/dynamodbstreams/attributevalue/shared_test.go @@ -38,6 +38,21 @@ type testStringSetStruct struct { Strings []string `dynamodbav:",stringset"` } +type testStringItem string + +func (t *testStringItem) UnmarshalDynamoDBStreamsAttributeValue(av types.AttributeValue) error { + v, ok := av.(*types.AttributeValueMemberS) + if !ok { + return fmt.Errorf("expecting string value") + } + *t = testStringItem(v.Value) + return nil +} + +type testStringSetWithUnmarshaler struct { + Items []testStringItem `dynamodbav:",stringset"` +} + type testIntAsStringStruct struct { Value int `dynamodbav:",string"` } @@ -201,6 +216,15 @@ var sharedTestCases = map[string]struct { actual: &testStringSetStruct{}, expected: testStringSetStruct{Strings: []string{"abc", "efg"}}, }, + "string Set with Unmarshaler": { + in: &types.AttributeValueMemberM{ + Value: map[string]types.AttributeValue{ + "Items": &types.AttributeValueMemberSS{Value: []string{"abc", "efg"}}, + }, + }, + actual: &testStringSetWithUnmarshaler{}, + expected: testStringSetWithUnmarshaler{Items: []testStringItem{"abc", "efg"}}, + }, "int value as string": { in: &types.AttributeValueMemberM{ Value: map[string]types.AttributeValue{ From afeb3cbff2eefcc0507836938a1320a331e1df36 Mon Sep 17 00:00:00 2001 From: Anatoly Rugalev Date: Mon, 18 Nov 2024 12:05:54 +0100 Subject: [PATCH 2/6] implement decoder flag --- feature/dynamodb/attributevalue/decode.go | 40 +++++++--- .../dynamodb/attributevalue/decode_test.go | 76 +++++++++++++++++++ .../dynamodb/attributevalue/shared_test.go | 24 ------ .../dynamodbstreams/attributevalue/decode.go | 40 +++++++--- .../attributevalue/decode_test.go | 76 +++++++++++++++++++ .../attributevalue/shared_test.go | 24 ------ 6 files changed, 208 insertions(+), 72 deletions(-) diff --git a/feature/dynamodb/attributevalue/decode.go b/feature/dynamodb/attributevalue/decode.go index a0695646e94..10973905f5b 100644 --- a/feature/dynamodb/attributevalue/decode.go +++ b/feature/dynamodb/attributevalue/decode.go @@ -243,6 +243,10 @@ type DecoderOptions struct { // call UnmarshalText on the target. If the attributevalue is a binary, its // value will be used to call UnmarshalBinary. UseEncodingUnmarshalers bool + + // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBAttributeValue + // on for individual set item instead of the whole set at once. + UnmarhalIndividualSetValues bool } // A Decoder provides unmarshaling AttributeValues to Go value types. @@ -447,11 +451,15 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) - if err != nil { - return err + if d.options.UnmarhalIndividualSetValues { + err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) + if err != nil { + return err + } + continue + } else { + return u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberBS{Value: bs}) } - continue } if err := d.decodeBinary(bs[i], elem); err != nil { return err @@ -586,11 +594,15 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) - if err != nil { - return err + if d.options.UnmarhalIndividualSetValues { + err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) + if err != nil { + return err + } + continue + } else { + return u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberNS{Value: ns}) } - continue } if err := d.decodeNumber(ns[i], elem, tag{}); err != nil { return err @@ -812,11 +824,15 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) - if err != nil { - return err + if d.options.UnmarhalIndividualSetValues { + err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) + if err != nil { + return err + } + continue + } else { + return u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberSS{Value: ss}) } - continue } if err := d.decodeString(ss[i], elem, tag{}); err != nil { return err diff --git a/feature/dynamodb/attributevalue/decode_test.go b/feature/dynamodb/attributevalue/decode_test.go index 9481ed5f7e8..88a46e77cc1 100644 --- a/feature/dynamodb/attributevalue/decode_test.go +++ b/feature/dynamodb/attributevalue/decode_test.go @@ -1268,3 +1268,79 @@ func TestUnmarshalBinary(t *testing.T) { t.Errorf("expected %v, got %v", expected, actual) } } + +type testStringItem string + +func (t *testStringItem) UnmarshalDynamoDBAttributeValue(av types.AttributeValue) error { + v, ok := av.(*types.AttributeValueMemberS) + if !ok { + return fmt.Errorf("expecting string value") + } + *t = testStringItem(v.Value) + return nil +} + +type testNumberItem float64 + +func (t *testNumberItem) UnmarshalDynamoDBAttributeValue(av types.AttributeValue) error { + v, ok := av.(*types.AttributeValueMemberN) + if !ok { + return fmt.Errorf("expecting number value") + } + n, err := strconv.ParseFloat(v.Value, 64) + if err != nil { + return err + } + *t = testNumberItem(n) + return nil +} + +type testBinaryItem []byte + +func (t *testBinaryItem) UnmarshalDynamoDBAttributeValue(av types.AttributeValue) error { + v, ok := av.(*types.AttributeValueMemberB) + if !ok { + return fmt.Errorf("expecting binary value") + } + *t = make([]byte, len(v.Value)) + copy(*t, v.Value) + return nil +} + +type testStringSetWithUnmarshaler struct { + Strings []testStringItem `dynamodbav:",stringset"` + Numbers []testNumberItem `dynamodbav:",numberset"` + Binaries []testBinaryItem `dynamodbav:",binaryset"` +} + +func TestUnmarshalIndividualSetValues(t *testing.T) { + in := &types.AttributeValueMemberM{ + Value: map[string]types.AttributeValue{ + "Strings": &types.AttributeValueMemberSS{ + Value: []string{"a", "b"}, + }, + "Numbers": &types.AttributeValueMemberNS{ + Value: []string{"1", "2"}, + }, + "Binaries": &types.AttributeValueMemberBS{ + Value: [][]byte{{1, 2}, {3, 4}}, + }, + }, + } + var actual testStringSetWithUnmarshaler + err := UnmarshalWithOptions(in, &actual, func(o *DecoderOptions) { + o.UnmarhalIndividualSetValues = true + }) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + expected := testStringSetWithUnmarshaler{ + Strings: []testStringItem{"a", "b"}, + Numbers: []testNumberItem{1, 2}, + Binaries: []testBinaryItem{{1, 2}, {3, 4}}, + } + if diff := cmpDiff(expected, actual); diff != "" { + t.Errorf("expect value match\n%s", diff) + } +} diff --git a/feature/dynamodb/attributevalue/shared_test.go b/feature/dynamodb/attributevalue/shared_test.go index 0eb1e643461..67a1791da50 100644 --- a/feature/dynamodb/attributevalue/shared_test.go +++ b/feature/dynamodb/attributevalue/shared_test.go @@ -38,21 +38,6 @@ type testStringSetStruct struct { Strings []string `dynamodbav:",stringset"` } -type testStringItem string - -func (t *testStringItem) UnmarshalDynamoDBAttributeValue(av types.AttributeValue) error { - v, ok := av.(*types.AttributeValueMemberS) - if !ok { - return fmt.Errorf("expecting string value") - } - *t = testStringItem(v.Value) - return nil -} - -type testStringSetWithUnmarshaler struct { - Items []testStringItem `dynamodbav:",stringset"` -} - type testIntAsStringStruct struct { Value int `dynamodbav:",string"` } @@ -216,15 +201,6 @@ var sharedTestCases = map[string]struct { actual: &testStringSetStruct{}, expected: testStringSetStruct{Strings: []string{"abc", "efg"}}, }, - "string Set with Unmarshaler": { - in: &types.AttributeValueMemberM{ - Value: map[string]types.AttributeValue{ - "Items": &types.AttributeValueMemberSS{Value: []string{"abc", "efg"}}, - }, - }, - actual: &testStringSetWithUnmarshaler{}, - expected: testStringSetWithUnmarshaler{Items: []testStringItem{"abc", "efg"}}, - }, "int value as string": { in: &types.AttributeValueMemberM{ Value: map[string]types.AttributeValue{ diff --git a/feature/dynamodbstreams/attributevalue/decode.go b/feature/dynamodbstreams/attributevalue/decode.go index 60e0fdb08ea..c1e5e57bdfb 100644 --- a/feature/dynamodbstreams/attributevalue/decode.go +++ b/feature/dynamodbstreams/attributevalue/decode.go @@ -243,6 +243,10 @@ type DecoderOptions struct { // call UnmarshalText on the target. If the attributevalue is a binary, its // value will be used to call UnmarshalBinary. UseEncodingUnmarshalers bool + + // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBStreamsAttributeValue + // on for individual set item instead of the whole set at once. + UnmarhalIndividualSetValues bool } // A Decoder provides unmarshaling AttributeValues to Go value types. @@ -447,11 +451,15 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) - if err != nil { - return err + if d.options.UnmarhalIndividualSetValues { + err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) + if err != nil { + return err + } + continue + } else { + return u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberBS{Value: bs}) } - continue } if err := d.decodeBinary(bs[i], elem); err != nil { return err @@ -586,11 +594,15 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) - if err != nil { - return err + if d.options.UnmarhalIndividualSetValues { + err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) + if err != nil { + return err + } + continue + } else { + return u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberNS{Value: ns}) } - continue } if err := d.decodeNumber(ns[i], elem, tag{}); err != nil { return err @@ -812,11 +824,15 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) - if err != nil { - return err + if d.options.UnmarhalIndividualSetValues { + err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) + if err != nil { + return err + } + continue + } else { + return u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberSS{Value: ss}) } - continue } if err := d.decodeString(ss[i], elem, tag{}); err != nil { return err diff --git a/feature/dynamodbstreams/attributevalue/decode_test.go b/feature/dynamodbstreams/attributevalue/decode_test.go index 1bccef17abb..ae0d4a416fb 100644 --- a/feature/dynamodbstreams/attributevalue/decode_test.go +++ b/feature/dynamodbstreams/attributevalue/decode_test.go @@ -1268,3 +1268,79 @@ func TestUnmarshalBinary(t *testing.T) { t.Errorf("expected %v, got %v", expected, actual) } } + +type testStringItem string + +func (t *testStringItem) UnmarshalDynamoDBStreasmAttributeValue(av types.AttributeValue) error { + v, ok := av.(*types.AttributeValueMemberS) + if !ok { + return fmt.Errorf("expecting string value") + } + *t = testStringItem(v.Value) + return nil +} + +type testNumberItem float64 + +func (t *testNumberItem) UnmarshalDynamoDBStreamsAttributeValue(av types.AttributeValue) error { + v, ok := av.(*types.AttributeValueMemberN) + if !ok { + return fmt.Errorf("expecting number value") + } + n, err := strconv.ParseFloat(v.Value, 64) + if err != nil { + return err + } + *t = testNumberItem(n) + return nil +} + +type testBinaryItem []byte + +func (t *testBinaryItem) UnmarshalDynamoDBStreamsAttributeValue(av types.AttributeValue) error { + v, ok := av.(*types.AttributeValueMemberB) + if !ok { + return fmt.Errorf("expecting binary value") + } + *t = make([]byte, len(v.Value)) + copy(*t, v.Value) + return nil +} + +type testStringSetWithUnmarshaler struct { + Strings []testStringItem `dynamodbav:",stringset"` + Numbers []testNumberItem `dynamodbav:",numberset"` + Binaries []testBinaryItem `dynamodbav:",binaryset"` +} + +func TestUnmarshalIndividualSetValues(t *testing.T) { + in := &types.AttributeValueMemberM{ + Value: map[string]types.AttributeValue{ + "Strings": &types.AttributeValueMemberSS{ + Value: []string{"a", "b"}, + }, + "Numbers": &types.AttributeValueMemberNS{ + Value: []string{"1", "2"}, + }, + "Binaries": &types.AttributeValueMemberBS{ + Value: [][]byte{{1, 2}, {3, 4}}, + }, + }, + } + var actual testStringSetWithUnmarshaler + err := UnmarshalWithOptions(in, &actual, func(o *DecoderOptions) { + o.UnmarhalIndividualSetValues = true + }) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + expected := testStringSetWithUnmarshaler{ + Strings: []testStringItem{"a", "b"}, + Numbers: []testNumberItem{1, 2}, + Binaries: []testBinaryItem{{1, 2}, {3, 4}}, + } + if diff := cmpDiff(expected, actual); diff != "" { + t.Errorf("expect value match\n%s", diff) + } +} diff --git a/feature/dynamodbstreams/attributevalue/shared_test.go b/feature/dynamodbstreams/attributevalue/shared_test.go index 17f0514f4e4..3a3721db420 100644 --- a/feature/dynamodbstreams/attributevalue/shared_test.go +++ b/feature/dynamodbstreams/attributevalue/shared_test.go @@ -38,21 +38,6 @@ type testStringSetStruct struct { Strings []string `dynamodbav:",stringset"` } -type testStringItem string - -func (t *testStringItem) UnmarshalDynamoDBStreamsAttributeValue(av types.AttributeValue) error { - v, ok := av.(*types.AttributeValueMemberS) - if !ok { - return fmt.Errorf("expecting string value") - } - *t = testStringItem(v.Value) - return nil -} - -type testStringSetWithUnmarshaler struct { - Items []testStringItem `dynamodbav:",stringset"` -} - type testIntAsStringStruct struct { Value int `dynamodbav:",string"` } @@ -216,15 +201,6 @@ var sharedTestCases = map[string]struct { actual: &testStringSetStruct{}, expected: testStringSetStruct{Strings: []string{"abc", "efg"}}, }, - "string Set with Unmarshaler": { - in: &types.AttributeValueMemberM{ - Value: map[string]types.AttributeValue{ - "Items": &types.AttributeValueMemberSS{Value: []string{"abc", "efg"}}, - }, - }, - actual: &testStringSetWithUnmarshaler{}, - expected: testStringSetWithUnmarshaler{Items: []testStringItem{"abc", "efg"}}, - }, "int value as string": { in: &types.AttributeValueMemberM{ Value: map[string]types.AttributeValue{ From b9cc851a020b5f119c8f3b74c78a38c0d093422b Mon Sep 17 00:00:00 2001 From: Anatoly Rugalev Date: Mon, 18 Nov 2024 12:08:11 +0100 Subject: [PATCH 3/6] copy --- feature/dynamodb/attributevalue/decode.go | 2 +- feature/dynamodbstreams/attributevalue/decode.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/dynamodb/attributevalue/decode.go b/feature/dynamodb/attributevalue/decode.go index 10973905f5b..ea3a789de64 100644 --- a/feature/dynamodb/attributevalue/decode.go +++ b/feature/dynamodb/attributevalue/decode.go @@ -245,7 +245,7 @@ type DecoderOptions struct { UseEncodingUnmarshalers bool // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBAttributeValue - // on for individual set item instead of the whole set at once. + // for individual set item instead of the whole set at once. UnmarhalIndividualSetValues bool } diff --git a/feature/dynamodbstreams/attributevalue/decode.go b/feature/dynamodbstreams/attributevalue/decode.go index c1e5e57bdfb..6b105dc3cdb 100644 --- a/feature/dynamodbstreams/attributevalue/decode.go +++ b/feature/dynamodbstreams/attributevalue/decode.go @@ -245,7 +245,7 @@ type DecoderOptions struct { UseEncodingUnmarshalers bool // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBStreamsAttributeValue - // on for individual set item instead of the whole set at once. + // for individual set item instead of the whole set at once. UnmarhalIndividualSetValues bool } From 0e605c25caca48975db4810cc8ea04b008709ab8 Mon Sep 17 00:00:00 2001 From: Anatoly Rugalev Date: Mon, 18 Nov 2024 12:08:37 +0100 Subject: [PATCH 4/6] copy --- feature/dynamodb/attributevalue/decode.go | 2 +- feature/dynamodbstreams/attributevalue/decode.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/dynamodb/attributevalue/decode.go b/feature/dynamodb/attributevalue/decode.go index ea3a789de64..0d16c8d7e5b 100644 --- a/feature/dynamodb/attributevalue/decode.go +++ b/feature/dynamodb/attributevalue/decode.go @@ -245,7 +245,7 @@ type DecoderOptions struct { UseEncodingUnmarshalers bool // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBAttributeValue - // for individual set item instead of the whole set at once. + // for each individual set item instead of the whole set at once. UnmarhalIndividualSetValues bool } diff --git a/feature/dynamodbstreams/attributevalue/decode.go b/feature/dynamodbstreams/attributevalue/decode.go index 6b105dc3cdb..62ae8cae0a6 100644 --- a/feature/dynamodbstreams/attributevalue/decode.go +++ b/feature/dynamodbstreams/attributevalue/decode.go @@ -245,7 +245,7 @@ type DecoderOptions struct { UseEncodingUnmarshalers bool // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBStreamsAttributeValue - // for individual set item instead of the whole set at once. + // for each individual set item instead of the whole set at once. UnmarhalIndividualSetValues bool } From c6ef5ec80460af0ada9eac7351f04bbd3f52944f Mon Sep 17 00:00:00 2001 From: Anatoly Rugalev Date: Mon, 18 Nov 2024 12:09:56 +0100 Subject: [PATCH 5/6] fix typo --- feature/dynamodb/attributevalue/decode.go | 8 ++++---- feature/dynamodb/attributevalue/decode_test.go | 2 +- feature/dynamodbstreams/attributevalue/decode.go | 8 ++++---- feature/dynamodbstreams/attributevalue/decode_test.go | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/feature/dynamodb/attributevalue/decode.go b/feature/dynamodb/attributevalue/decode.go index 0d16c8d7e5b..a32abc42b55 100644 --- a/feature/dynamodb/attributevalue/decode.go +++ b/feature/dynamodb/attributevalue/decode.go @@ -246,7 +246,7 @@ type DecoderOptions struct { // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBAttributeValue // for each individual set item instead of the whole set at once. - UnmarhalIndividualSetValues bool + UnmarshalIndividualSetValues bool } // A Decoder provides unmarshaling AttributeValues to Go value types. @@ -451,7 +451,7 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarhalIndividualSetValues { + if d.options.UnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) if err != nil { return err @@ -594,7 +594,7 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarhalIndividualSetValues { + if d.options.UnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) if err != nil { return err @@ -824,7 +824,7 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarhalIndividualSetValues { + if d.options.UnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) if err != nil { return err diff --git a/feature/dynamodb/attributevalue/decode_test.go b/feature/dynamodb/attributevalue/decode_test.go index 88a46e77cc1..2b18bda13f5 100644 --- a/feature/dynamodb/attributevalue/decode_test.go +++ b/feature/dynamodb/attributevalue/decode_test.go @@ -1329,7 +1329,7 @@ func TestUnmarshalIndividualSetValues(t *testing.T) { } var actual testStringSetWithUnmarshaler err := UnmarshalWithOptions(in, &actual, func(o *DecoderOptions) { - o.UnmarhalIndividualSetValues = true + o.UnmarshalIndividualSetValues = true }) if err != nil { t.Fatalf("expect no error, got %v", err) diff --git a/feature/dynamodbstreams/attributevalue/decode.go b/feature/dynamodbstreams/attributevalue/decode.go index 62ae8cae0a6..8f3bac30efc 100644 --- a/feature/dynamodbstreams/attributevalue/decode.go +++ b/feature/dynamodbstreams/attributevalue/decode.go @@ -246,7 +246,7 @@ type DecoderOptions struct { // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBStreamsAttributeValue // for each individual set item instead of the whole set at once. - UnmarhalIndividualSetValues bool + UnmarshalIndividualSetValues bool } // A Decoder provides unmarshaling AttributeValues to Go value types. @@ -451,7 +451,7 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarhalIndividualSetValues { + if d.options.UnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) if err != nil { return err @@ -594,7 +594,7 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarhalIndividualSetValues { + if d.options.UnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) if err != nil { return err @@ -824,7 +824,7 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarhalIndividualSetValues { + if d.options.UnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) if err != nil { return err diff --git a/feature/dynamodbstreams/attributevalue/decode_test.go b/feature/dynamodbstreams/attributevalue/decode_test.go index ae0d4a416fb..c6be54ad2d0 100644 --- a/feature/dynamodbstreams/attributevalue/decode_test.go +++ b/feature/dynamodbstreams/attributevalue/decode_test.go @@ -1329,7 +1329,7 @@ func TestUnmarshalIndividualSetValues(t *testing.T) { } var actual testStringSetWithUnmarshaler err := UnmarshalWithOptions(in, &actual, func(o *DecoderOptions) { - o.UnmarhalIndividualSetValues = true + o.UnmarshalIndividualSetValues = true }) if err != nil { t.Fatalf("expect no error, got %v", err) From 88c0e1e3db7a5c1320adfce01b206b6b316391b6 Mon Sep 17 00:00:00 2001 From: Anatoly Rugalev Date: Fri, 6 Dec 2024 11:35:53 +0100 Subject: [PATCH 6/6] rename decoder option, add issue reference --- feature/dynamodb/attributevalue/decode.go | 9 +++++---- feature/dynamodb/attributevalue/decode_test.go | 2 +- feature/dynamodbstreams/attributevalue/decode.go | 9 +++++---- feature/dynamodbstreams/attributevalue/decode_test.go | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/feature/dynamodb/attributevalue/decode.go b/feature/dynamodb/attributevalue/decode.go index a32abc42b55..9be77b9912a 100644 --- a/feature/dynamodb/attributevalue/decode.go +++ b/feature/dynamodb/attributevalue/decode.go @@ -246,7 +246,8 @@ type DecoderOptions struct { // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBAttributeValue // for each individual set item instead of the whole set at once. - UnmarshalIndividualSetValues bool + // See issue #2895. + FixUnmarshalIndividualSetValues bool } // A Decoder provides unmarshaling AttributeValues to Go value types. @@ -451,7 +452,7 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarshalIndividualSetValues { + if d.options.FixUnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) if err != nil { return err @@ -594,7 +595,7 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarshalIndividualSetValues { + if d.options.FixUnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) if err != nil { return err @@ -824,7 +825,7 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarshalIndividualSetValues { + if d.options.FixUnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) if err != nil { return err diff --git a/feature/dynamodb/attributevalue/decode_test.go b/feature/dynamodb/attributevalue/decode_test.go index 2b18bda13f5..c99887eacbb 100644 --- a/feature/dynamodb/attributevalue/decode_test.go +++ b/feature/dynamodb/attributevalue/decode_test.go @@ -1329,7 +1329,7 @@ func TestUnmarshalIndividualSetValues(t *testing.T) { } var actual testStringSetWithUnmarshaler err := UnmarshalWithOptions(in, &actual, func(o *DecoderOptions) { - o.UnmarshalIndividualSetValues = true + o.FixUnmarshalIndividualSetValues = true }) if err != nil { t.Fatalf("expect no error, got %v", err) diff --git a/feature/dynamodbstreams/attributevalue/decode.go b/feature/dynamodbstreams/attributevalue/decode.go index 8f3bac30efc..f8ddfecd09c 100644 --- a/feature/dynamodbstreams/attributevalue/decode.go +++ b/feature/dynamodbstreams/attributevalue/decode.go @@ -246,7 +246,8 @@ type DecoderOptions struct { // When enabled, the decoder will call Unmarshaler.UnmarshalDynamoDBStreamsAttributeValue // for each individual set item instead of the whole set at once. - UnmarshalIndividualSetValues bool + // See issue #2895. + FixUnmarshalIndividualSetValues bool } // A Decoder provides unmarshaling AttributeValues to Go value types. @@ -451,7 +452,7 @@ func (d *Decoder) decodeBinarySet(bs [][]byte, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarshalIndividualSetValues { + if d.options.FixUnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberB{Value: bs[i]}) if err != nil { return err @@ -594,7 +595,7 @@ func (d *Decoder) decodeNumberSet(ns []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarshalIndividualSetValues { + if d.options.FixUnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberN{Value: ns[i]}) if err != nil { return err @@ -824,7 +825,7 @@ func (d *Decoder) decodeStringSet(ss []string, v reflect.Value) error { } u, elem := indirect[Unmarshaler](v.Index(i), indirectOptions{}) if u != nil { - if d.options.UnmarshalIndividualSetValues { + if d.options.FixUnmarshalIndividualSetValues { err := u.UnmarshalDynamoDBStreamsAttributeValue(&types.AttributeValueMemberS{Value: ss[i]}) if err != nil { return err diff --git a/feature/dynamodbstreams/attributevalue/decode_test.go b/feature/dynamodbstreams/attributevalue/decode_test.go index c6be54ad2d0..666fdf1c004 100644 --- a/feature/dynamodbstreams/attributevalue/decode_test.go +++ b/feature/dynamodbstreams/attributevalue/decode_test.go @@ -1329,7 +1329,7 @@ func TestUnmarshalIndividualSetValues(t *testing.T) { } var actual testStringSetWithUnmarshaler err := UnmarshalWithOptions(in, &actual, func(o *DecoderOptions) { - o.UnmarshalIndividualSetValues = true + o.FixUnmarshalIndividualSetValues = true }) if err != nil { t.Fatalf("expect no error, got %v", err)