Skip to content

Commit

Permalink
marshal: descend through all interfaces/pointers when looking for tim…
Browse files Browse the repository at this point in the history
…e.Time

Previously, we would ignore an interface{} containing a *time.Time and
treat it as a TextMarshaler.

Fixes #82
  • Loading branch information
DHowett committed Dec 25, 2024
1 parent 6b86383 commit 2e1fca7
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
9 changes: 8 additions & 1 deletion marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ func (p *Encoder) marshalTime(val reflect.Value) cfValue {
return cfDate(time)
}

func innermostValue(val reflect.Value) reflect.Value {
for val.Kind() == reflect.Ptr || (val.Kind() == reflect.Interface && val.NumMethod() == 0) {
val = val.Elem()
}
return val
}

func (p *Encoder) marshal(val reflect.Value) cfValue {
if !val.IsValid() {
return nil
Expand All @@ -105,7 +112,7 @@ func (p *Encoder) marshal(val reflect.Value) cfValue {
return p.marshalTime(val)
}
if val.Kind() == reflect.Ptr || (val.Kind() == reflect.Interface && val.NumMethod() == 0) {
ival := val.Elem()
ival := innermostValue(val)
if ival.IsValid() && ival.Type() == timeType {
return p.marshalTime(ival)
}
Expand Down
23 changes: 23 additions & 0 deletions marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,26 @@ func TestInterfaceFieldMarshal(t *testing.T) {
t.Log("expect non-zero data")
}
}

func TestMarshalInterfaceFieldPtrTime(t *testing.T) {
type X struct {
C interface{} // C's type is unknown
}

var sentinelTime = time.Date(2013, 11, 27, 0, 34, 0, 0, time.UTC)
x := &X{
C: &sentinelTime,
}

e := &Encoder{}
rval := reflect.ValueOf(x)
cf := e.marshal(rval)

if dict, ok := cf.(*cfDictionary); ok {
if _, ok := dict.values[0].(cfDate); !ok {
t.Error("inner value is not a cfDate")
}
} else {
t.Error("failed to marshal toplevel dictionary (?)")
}
}

0 comments on commit 2e1fca7

Please sign in to comment.