Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add another test and fix lint errors #466

Merged
merged 1 commit into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 24 additions & 22 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,21 +293,23 @@ func (m NilContainersMode) valid() bool {
return m >= 0 && m < maxNilContainersMode
}

// OmitEmptyMode specifies how to encode the fields with omitempty tag
// The default behavior omits if field value would encode as empty JSON value
// OmitEmptyMode specifies how to encode struct fields with omitempty tag.
// The default behavior omits if field value would encode as empty CBOR value.
type OmitEmptyMode int

const (
// OmitEmptyCBORValue specifies that fields tagged with "omitempty" should be
// omitted from encoding if the field would be encoded as an empty CBOR value,
// such as CBOR false, 0, 0.0, nil, empty byte, empty string, empty array,
// empty struct or empty map.
// OmitEmptyCBORValue specifies that struct fields tagged with "omitempty"
// should be omitted from encoding if the field would be encoded as an empty
// CBOR value, such as CBOR false, 0, 0.0, nil, empty byte, empty string,
// empty array, or empty map.
OmitEmptyCBORValue OmitEmptyMode = iota

// OmitEmptyGoValue specifies that fields tagged with "omitempty" should be
// omitted from encoding if the field has an empty Go value, defined as false, 0, a nil pointer,
// a nil interface value, and any empty array, slice, map, or string.
// This behavior is the same as the current (aka v1) encoding/json package included in Go.
// OmitEmptyGoValue specifies that struct fields tagged with "omitempty"
// should be omitted from encoding if the field has an empty Go value,
// defined as false, 0, 0.0, a nil pointer, a nil interface value, and
// any empty array, slice, map, or string.
// This behavior is the same as the current (aka v1) encoding/json package
// included in Go.
OmitEmptyGoValue

maxOmitEmptyMode
Expand Down Expand Up @@ -351,7 +353,7 @@ type EncOptions struct {
// TagsMd specifies whether to allow CBOR tags (major type 6).
TagsMd TagsMode

// OmitEmptyMode specifies how to encode the fields with omitempty tag
// OmitEmptyMode specifies how to encode struct fields with omitempty tag.
OmitEmpty OmitEmptyMode
}

Expand Down Expand Up @@ -1435,43 +1437,43 @@ func getEncodeIndirectValueFunc(t reflect.Type) encodeFunc {
}
}

func alwaysNotEmpty(em *encMode, _ reflect.Value) (empty bool, err error) {
func alwaysNotEmpty(_ *encMode, _ reflect.Value) (empty bool, err error) {
return false, nil
}

func isEmptyBool(em *encMode, v reflect.Value) (bool, error) {
func isEmptyBool(_ *encMode, v reflect.Value) (bool, error) {
return !v.Bool(), nil
}

func isEmptyInt(em *encMode, v reflect.Value) (bool, error) {
func isEmptyInt(_ *encMode, v reflect.Value) (bool, error) {
return v.Int() == 0, nil
}

func isEmptyUint(em *encMode, v reflect.Value) (bool, error) {
func isEmptyUint(_ *encMode, v reflect.Value) (bool, error) {
return v.Uint() == 0, nil
}

func isEmptyFloat(em *encMode, v reflect.Value) (bool, error) {
func isEmptyFloat(_ *encMode, v reflect.Value) (bool, error) {
return v.Float() == 0.0, nil
}

func isEmptyString(em *encMode, v reflect.Value) (bool, error) {
func isEmptyString(_ *encMode, v reflect.Value) (bool, error) {
return v.Len() == 0, nil
}

func isEmptySlice(em *encMode, v reflect.Value) (bool, error) {
func isEmptySlice(_ *encMode, v reflect.Value) (bool, error) {
return v.Len() == 0, nil
}

func isEmptyMap(em *encMode, v reflect.Value) (bool, error) {
func isEmptyMap(_ *encMode, v reflect.Value) (bool, error) {
return v.Len() == 0, nil
}

func isEmptyPtr(em *encMode, v reflect.Value) (bool, error) {
func isEmptyPtr(_ *encMode, v reflect.Value) (bool, error) {
return v.IsNil(), nil
}

func isEmptyIntf(em *encMode, v reflect.Value) (bool, error) {
func isEmptyIntf(_ *encMode, v reflect.Value) (bool, error) {
return v.IsNil(), nil
}

Expand Down Expand Up @@ -1522,7 +1524,7 @@ func isEmptyStruct(em *encMode, v reflect.Value) (bool, error) {
return true, nil
}

func isEmptyBinaryMarshaler(em *encMode, v reflect.Value) (bool, error) {
func isEmptyBinaryMarshaler(_ *encMode, v reflect.Value) (bool, error) {
m, ok := v.Interface().(encoding.BinaryMarshaler)
if !ok {
pv := reflect.New(v.Type())
Expand Down
44 changes: 36 additions & 8 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,34 @@ func TestOmitEmptyForStruct2(t *testing.T) {
testRoundTrip(t, []roundTripTest{{"non-default values", v, want}}, em, dm)
}

func TestInvalidOmitEmptyMode(t *testing.T) {
for _, tc := range []struct {
name string
opts EncOptions
wantErrorMsg string
}{
{
name: "below range of valid modes",
opts: EncOptions{OmitEmpty: -1},
wantErrorMsg: "cbor: invalid OmitEmpty -1",
},
{
name: "above range of valid modes",
opts: EncOptions{OmitEmpty: 101},
wantErrorMsg: "cbor: invalid OmitEmpty 101",
},
} {
t.Run(tc.name, func(t *testing.T) {
_, err := tc.opts.EncMode()
if err == nil {
t.Errorf("EncMode() didn't return an error")
} else if err.Error() != tc.wantErrorMsg {
t.Errorf("EncMode() returned error %q, want %q", err.Error(), tc.wantErrorMsg)
}
})
}
}

func TestOmitEmptyMode(t *testing.T) {
type T1 struct{}
type T struct {
Expand Down Expand Up @@ -1154,8 +1182,8 @@ func TestOmitEmptyMode(t *testing.T) {

v := T{}

// {"b": false, "ui": 0, "i":0, "f": 0, "s": "", "slc": nil, "m": nil, "p": nil, "intf": nil, "str": {}, "stro": {}}
wantGoValue := []byte{
// {"b": false, "ui": 0, "i": 0, "f": 0.0, "s": "", "slc": null, "m": null, "p": null, "intf": null, "str": {}, "stro": {}}
wantDataWithOmitEmptyGoValue := []byte{
0xab,
0x61, 0x62, 0xf4,
0x62, 0x75, 0x69, 0x00,
Expand All @@ -1170,8 +1198,8 @@ func TestOmitEmptyMode(t *testing.T) {
0x64, 0x73, 0x74, 0x72, 0x6F, 0xa0,
}

// {"b": false, "ui": 0, "i":0, "f": 0, "s": "", "slc": nil, "m": nil, "p": nil, "intf": nil, "str": nil, "stro": nil}
wantCborValue := []byte{
// {"b": false, "ui": 0, "i": 0, "f": 0.0, "s": "", "slc": null, "m": null, "p": null, "intf": null, "str": {}}
wantDataWithOmitEmptyCBORValue := []byte{
0xaa,
0x61, 0x62, 0xf4,
0x62, 0x75, 0x69, 0x00,
Expand All @@ -1185,11 +1213,11 @@ func TestOmitEmptyMode(t *testing.T) {
0x63, 0x73, 0x74, 0x72, 0xa0,
}

em_govalue, _ := EncOptions{OmitEmpty: OmitEmptyGoValue}.EncMode()
em_cborvalue, _ := EncOptions{OmitEmpty: OmitEmptyCBORValue}.EncMode()
emOmitEmptyGoValue, _ := EncOptions{OmitEmpty: OmitEmptyGoValue}.EncMode()
emOmitEmptyCBORValue, _ := EncOptions{OmitEmpty: OmitEmptyCBORValue}.EncMode()
dm, _ := DecOptions{}.DecMode()
testRoundTrip(t, []roundTripTest{{"OmitEmptyGoValue default values", v, wantGoValue}}, em_govalue, dm)
testRoundTrip(t, []roundTripTest{{"OmitEmptyCBORValue values", v, wantCborValue}}, em_cborvalue, dm)
testRoundTrip(t, []roundTripTest{{"OmitEmptyGoValue (default) ", v, wantDataWithOmitEmptyGoValue}}, emOmitEmptyGoValue, dm)
testRoundTrip(t, []roundTripTest{{"OmitEmptyCBORValue", v, wantDataWithOmitEmptyCBORValue}}, emOmitEmptyCBORValue, dm)
}

func TestOmitEmptyForNestedStruct(t *testing.T) {
Expand Down
Loading