Repository: fxamacker/cbor
Pull request #377 (2022-12-30 00:41:30)

Refactor NilContainersMode option
Changes:
- Moved NilContainersMode from decode.go to encode.go because it is only an encoding option.
- Renamed NullForNil to NilContainerAsNull.
- Renamed EmptyForNil to NilContainerAsEmpty.
- Updated and added some comments.




Patch:
diff --git a/decode.go b/decode.go
index 8a91296..c444451 100644
--- a/decode.go
+++ b/decode.go
@@ -210,23 +210,6 @@ func (m IndefLengthMode) valid() bool {
 	return m < maxIndefLengthMode
 }
 
-// NilContainersMode specifies how to encode []Type(nil) and map[Key]Type(nil).
-type NilContainersMode int
-
-const (
-	// NullForNil enforces null for []Type(nil)/map[Key]Type(nil).
-	NullForNil NilContainersMode = iota
-
-	// EmptyForNil enforces empty map/list for []Type(nil)/map[Key]Type(nil).
-	EmptyForNil
-
-	maxNilContainersMode
-)
-
-func (m NilContainersMode) valid() bool {
-	return m < maxNilContainersMode
-}
-
 // TagsMode specifies whether to allow CBOR tags.
 type TagsMode int
 
diff --git a/encode.go b/encode.go
index 99478cd..a2a2657 100644
--- a/encode.go
+++ b/encode.go
@@ -264,6 +264,25 @@ func (bim BigIntConvertMode) valid() bool {
 	return bim < maxBigIntConvert
 }
 
+// NilContainersMode specifies how to encode nil slices and maps.
+type NilContainersMode int
+
+const (
+	// NilContainerAsNull encodes nil slices and maps as CBOR null.
+	// This is the default.
+	NilContainerAsNull NilContainersMode = iota
+
+	// NilContainerAsEmpty encodes nil slices and maps as
+	// empty container (CBOR bytestring, array, or map).
+	NilContainerAsEmpty
+
+	maxNilContainersMode
+)
+
+func (m NilContainersMode) valid() bool {
+	return m < maxNilContainersMode
+}
+
 // EncOptions specifies encoding options.
 type EncOptions struct {
 	// Sort specifies sorting order.
@@ -292,7 +311,7 @@ type EncOptions struct {
 	// IndefLength specifies whether to allow indefinite length CBOR items.
 	IndefLength IndefLengthMode
 
-	// NilContainers specifies how to encode map[Key]Type(nil)/[]Type(nil)
+	// NilContainers specifies how to encode nil slices and maps.
 	NilContainers NilContainersMode
 
 	// TagsMd specifies whether to allow CBOR tags (major type 6).
@@ -795,7 +814,7 @@ func encodeFloat64(e *encoderBuffer, f64 float64) error {
 
 func encodeByteString(e *encoderBuffer, em *encMode, v reflect.Value) error {
 	vk := v.Kind()
-	if vk == reflect.Slice && v.IsNil() && em.nilContainers == NullForNil {
+	if vk == reflect.Slice && v.IsNil() && em.nilContainers == NilContainerAsNull {
 		e.Write(cborNil)
 		return nil
 	}
@@ -832,7 +851,7 @@ type arrayEncodeFunc struct {
 }
 
 func (ae arrayEncodeFunc) encode(e *encoderBuffer, em *encMode, v reflect.Value) error {
-	if v.Kind() == reflect.Slice && v.IsNil() && em.nilContainers == NullForNil {
+	if v.Kind() == reflect.Slice && v.IsNil() && em.nilContainers == NilContainerAsNull {
 		e.Write(cborNil)
 		return nil
 	}
@@ -857,7 +876,7 @@ type mapEncodeFunc struct {
 }
 
 func (me mapEncodeFunc) encode(e *encoderBuffer, em *encMode, v reflect.Value) error {
-	if v.IsNil() && em.nilContainers == NullForNil {
+	if v.IsNil() && em.nilContainers == NilContainerAsNull {
 		e.Write(cborNil)
 		return nil
 	}


Test patch:
diff --git a/encode_test.go b/encode_test.go
index a0d49ba..15b4c6f 100644
--- a/encode_test.go
+++ b/encode_test.go
@@ -2858,22 +2858,23 @@ func TestInvalidInfConvert(t *testing.T) {
 }
 
 func TestNilContainers(t *testing.T) {
-	nilContainersNull := EncOptions{NilContainers: NullForNil}
-	nilContainersEmpty := EncOptions{NilContainers: EmptyForNil}
+	nilContainersNull := EncOptions{NilContainers: NilContainerAsNull}
+	nilContainersEmpty := EncOptions{NilContainers: NilContainerAsEmpty}
+
 	testCases := []struct {
 		name         string
 		v            interface{}
 		opts         EncOptions
 		wantCborData []byte
 	}{
-		{"map(nil) as null", map[string]string(nil), nilContainersNull, hexDecode("f6")},
-		{"map(nil) as empty map", map[string]string(nil), nilContainersEmpty, hexDecode("a0")},
+		{"map(nil) as CBOR null", map[string]string(nil), nilContainersNull, hexDecode("f6")},
+		{"map(nil) as CBOR empty map", map[string]string(nil), nilContainersEmpty, hexDecode("a0")},
 
-		{"slice(nil) as null", []int(nil), nilContainersNull, hexDecode("f6")},
-		{"slice(nil) as empty list", []int(nil), nilContainersEmpty, hexDecode("80")},
+		{"slice(nil) as CBOR null", []int(nil), nilContainersNull, hexDecode("f6")},
+		{"slice(nil) as CBOR empty array", []int(nil), nilContainersEmpty, hexDecode("80")},
 
-		{"[]byte(nil) as null", []byte(nil), nilContainersNull, hexDecode("f6")},
-		{"[]byte(nil) as empty bytestring", []byte(nil), nilContainersEmpty, hexDecode("40")},
+		{"[]byte(nil) as CBOR null", []byte(nil), nilContainersNull, hexDecode("f6")},
+		{"[]byte(nil) as CBOR empty bytestring", []byte(nil), nilContainersEmpty, hexDecode("40")},
 	}
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
@@ -3355,7 +3356,7 @@ func TestEncOptions(t *testing.T) {
 		Time:          TimeRFC3339Nano,
 		TimeTag:       EncTagRequired,
 		IndefLength:   IndefLengthForbidden,
-		NilContainers: NullForNil,
+		NilContainers: NilContainerAsNull,
 		TagsMd:        TagsAllowed,
 	}
 	em, err := opts1.EncMode()