Skip to content

Commit 929b0a7

Browse files
authored
Merge pull request #361 from BurntSushi/p-omitempty
Don't panic with 'omitempty' and uncomparable type
2 parents 2e74712 + 8d9ffad commit 929b0a7

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

encode.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ func (enc *Encoder) eElement(rv reflect.Value) {
261261
enc.eElement(reflect.ValueOf(v))
262262
return
263263
}
264-
encPanic(errors.New(fmt.Sprintf("Unable to convert \"%s\" to neither int64 nor float64", n)))
264+
encPanic(fmt.Errorf("unable to convert %q to int64 or float64", n))
265265
}
266266

267267
switch rv.Kind() {
@@ -504,7 +504,8 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
504504
if opts.name != "" {
505505
keyName = opts.name
506506
}
507-
if opts.omitempty && isEmpty(fieldVal) {
507+
508+
if opts.omitempty && enc.isEmpty(fieldVal) {
508509
continue
509510
}
510511
if opts.omitzero && isZero(fieldVal) {
@@ -648,11 +649,14 @@ func isZero(rv reflect.Value) bool {
648649
return false
649650
}
650651

651-
func isEmpty(rv reflect.Value) bool {
652+
func (enc *Encoder) isEmpty(rv reflect.Value) bool {
652653
switch rv.Kind() {
653654
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
654655
return rv.Len() == 0
655656
case reflect.Struct:
657+
if !rv.Type().Comparable() {
658+
encPanic(fmt.Errorf("type %q cannot be used with omitempty as it's uncomparable", rv.Type()))
659+
}
656660
return reflect.Zero(rv.Type()).Interface() == rv.Interface()
657661
case reflect.Bool:
658662
return !rv.Bool()

encode_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,38 @@ time = 1985-06-18T15:16:17Z
212212
v, expected, nil)
213213
}
214214

215+
func TestEncodeWithOmitEmptyError(t *testing.T) {
216+
type nest struct {
217+
Field []string `toml:"Field,omitempty"`
218+
}
219+
220+
tests := []struct {
221+
in interface{}
222+
wantErr string
223+
}{
224+
{ // Make sure it doesn't panic on uncomparable types; #360
225+
struct {
226+
Values nest `toml:"values,omitempty"`
227+
Empty nest `toml:"empty,omitempty"`
228+
}{Values: nest{[]string{"XXX"}}},
229+
"cannot be used with omitempty as it's uncomparable",
230+
},
231+
}
232+
233+
for _, tt := range tests {
234+
t.Run("", func(t *testing.T) {
235+
buf := new(bytes.Buffer)
236+
err := NewEncoder(buf).Encode(tt.in)
237+
if !errorContains(err, tt.wantErr) {
238+
t.Fatalf("wrong error: %v", err)
239+
}
240+
if buf.String() != "" {
241+
t.Errorf("output not empty:\n%s", buf)
242+
}
243+
})
244+
}
245+
}
246+
215247
func TestEncodeWithOmitZero(t *testing.T) {
216248
type simple struct {
217249
Number int `toml:"number,omitzero"`

0 commit comments

Comments
 (0)