Skip to content

Commit

Permalink
Merge pull request #466 from fxamacker/fxamacker/fix-lint
Browse files Browse the repository at this point in the history
Add another test and fix lint errors
  • Loading branch information
fxamacker authored Jan 7, 2024
2 parents 0cf56c3 + c5c410b commit 83ec0aa
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 30 deletions.
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

0 comments on commit 83ec0aa

Please sign in to comment.