Skip to content

Commit

Permalink
remove redundent tryMarshaler calls in encodeString and encodeNumber
Browse files Browse the repository at this point in the history
both encodeString and encodeNumber get called from encode after tryMarshaller failled

added benchmark for list of int and struct of int and string fields
  • Loading branch information
Or Hayat committed Mar 20, 2024
1 parent 91a5e15 commit 2aa06b0
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 10 deletions.
10 changes: 0 additions & 10 deletions feature/dynamodb/attributevalue/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -714,11 +714,6 @@ func (e *Encoder) encodeScalar(v reflect.Value, fieldTag tag) (types.AttributeVa
}

func (e *Encoder) encodeNumber(v reflect.Value) (types.AttributeValue, error) {
if av, err := tryMarshaler(v); err != nil {
return nil, err
} else if av != nil {
return av, nil
}

var out string
switch v.Kind() {
Expand All @@ -742,11 +737,6 @@ func (e *Encoder) encodeNumber(v reflect.Value) (types.AttributeValue, error) {
}

func (e *Encoder) encodeString(v reflect.Value) (types.AttributeValue, error) {
if av, err := tryMarshaler(v); err != nil {
return nil, err
} else if av != nil {
return av, nil
}

switch v.Kind() {
case reflect.String:
Expand Down
91 changes: 91 additions & 0 deletions feature/dynamodb/attributevalue/encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,97 @@ func TestMarshalMashaler(t *testing.T) {
}
}

type customBoolStringMarshaler string

func (m customBoolStringMarshaler) MarshalDynamoDBAttributeValue() (types.AttributeValue, error) {

if b, err := strconv.ParseBool(string(m)); err == nil {
return &types.AttributeValueMemberBOOL{Value: b}, nil
}

return &types.AttributeValueMemberS{Value: string(m)}, nil
}

func TestCustomStringMarshaler(t *testing.T) {
cases := []struct {
expected types.AttributeValue
input string
}{
{
expected: &types.AttributeValueMemberBOOL{Value: false},
input: "false",
},
{
expected: &types.AttributeValueMemberBOOL{Value: true},
input: "true",
},
{
expected: &types.AttributeValueMemberS{Value: "ABC"},
input: "ABC",
},
}

for _, testCase := range cases {
input := customBoolStringMarshaler(testCase.input)
actual, err := Marshal(input)
if err != nil {
t.Errorf("got unexpected error %v for input %v", err, testCase.input)
}
if diff := cmpDiff(testCase.expected, actual); len(diff) != 0 {
t.Errorf("expected match but got:%s", diff)
}
}
}

type customGradeMarshaler uint

func (m customGradeMarshaler) MarshalDynamoDBAttributeValue() (types.AttributeValue, error) {
if int(m) > 100 {
return nil, fmt.Errorf("grade cant be larger then 100")
}
return &types.AttributeValueMemberN{Value: strconv.FormatUint(uint64(m), 10)}, nil
}

func TestCustomNumberMarshaler(t *testing.T) {
cases := []struct {
expectedErr bool
input uint
expected types.AttributeValue
}{
{
expectedErr: false,
input: 50,
expected: &types.AttributeValueMemberN{Value: "50"},
},
{
expectedErr: false,
input: 90,
expected: &types.AttributeValueMemberN{Value: "90"},
},
{
expectedErr: true,
input: 150,
expected: nil,
},
}

for _, testCase := range cases {
input := customGradeMarshaler(testCase.input)
actual, err := Marshal(customGradeMarshaler(input))
if testCase.expectedErr && err == nil {
t.Errorf("expected error but got nil for input %v", testCase.input)
continue
}
if !testCase.expectedErr && err != nil {
t.Errorf("got unexpected error %v for input %v", err, testCase.input)
continue
}
if diff := cmpDiff(testCase.expected, actual); len(diff) != 0 {
t.Errorf("expected match but got:%s", diff)
}
}
}

type testOmitEmptyElemListStruct struct {
Values []string `dynamodbav:",omitemptyelem"`
}
Expand Down
54 changes: 54 additions & 0 deletions feature/dynamodb/attributevalue/marshaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,60 @@ func BenchmarkMarshalOneMember(b *testing.B) {
})
}

func BenchmarkList20Ints(b *testing.B) {
input := []int{}
for i := 0; i < 20; i++ {
input = append(input, i)
}

b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := Marshal(input)
if err != nil {
b.Fatal(err)
}
}
})
}

func BenchmarkStruct10Fields(b *testing.B) {

type struct10Fields struct {
Field1 int
Field2 string
Field3 int
Field4 string
Field5 string
Field6 string
Field7 int
Field8 string
Field9 int
Field10 int
}

input := struct10Fields{
Field1: 10,
Field2: "ASD",
Field3: 70,
Field4: "qqqqq",
Field5: "AAA",
Field6: "bbb",
Field7: 63,
Field8: "aa",
Field9: 10,
Field10: 63,
}

b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_, err := Marshal(input)
if err != nil {
b.Fatal(err)
}
}
})
}

func BenchmarkMarshalTwoMembers(b *testing.B) {
fieldCache = &fieldCacher{}

Expand Down

0 comments on commit 2aa06b0

Please sign in to comment.