Merge branch 'v1' of github.com:go-yaml/yaml into v1
diff --git a/decode.go b/decode.go index ab2b8f7..74eda3c 100644 --- a/decode.go +++ b/decode.go
@@ -3,6 +3,7 @@ import ( "reflect" "strconv" + "time" ) const ( @@ -211,6 +212,16 @@ // returned to call SetYAML() with the value of *out once it's defined. // func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (set func()) { + if (*out).Kind() != reflect.Ptr && (*out).CanAddr() { + setter, _ := (*out).Addr().Interface().(Setter) + if setter != nil { + var arg interface{} + *out = reflect.ValueOf(&arg).Elem() + return func() { + *good = setter.SetYAML(tag, arg) + } + } + } again := true for again { again = false @@ -279,6 +290,8 @@ return good } +var durationType = reflect.TypeOf(time.Duration(0)) + func (d *decoder) scalar(n *node, out reflect.Value) (good bool) { var tag string var resolved interface{} @@ -321,6 +334,14 @@ out.SetInt(int64(resolved)) good = true } + case string: + if out.Type() == durationType { + d, err := time.ParseDuration(resolved) + if err == nil { + out.SetInt(int64(d)) + good = true + } + } } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: switch resolved := resolved.(type) {
diff --git a/decode_test.go b/decode_test.go index 5702909..d2b45b3 100644 --- a/decode_test.go +++ b/decode_test.go
@@ -1,10 +1,11 @@ package yaml_test import ( - . "launchpad.net/gocheck" + . "gopkg.in/check.v1" "gopkg.in/yaml.v1" "math" "reflect" + "time" ) var unmarshalIntTest = 123 @@ -364,6 +365,12 @@ "a: 50cent_of_dollar", map[string]interface{}{"a": "50cent_of_dollar"}, }, + + // Duration + { + "a: 3s", + map[string]time.Duration{"a": 3 * time.Second}, + }, } type inlineB struct { @@ -458,17 +465,31 @@ return true } -type typeWithSetterField struct { +type setterPointerType struct { Field *typeWithSetter "_" } -func (s *S) TestUnmarshalWithSetter(c *C) { +type setterValueType struct { + Field typeWithSetter "_" +} + +func (s *S) TestUnmarshalWithPointerSetter(c *C) { for _, item := range setterTests { - obj := &typeWithSetterField{} + obj := &setterPointerType{} err := yaml.Unmarshal([]byte(item.data), obj) c.Assert(err, IsNil) - c.Assert(obj.Field, NotNil, - Commentf("Pointer not initialized (%#v)", item.value)) + c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) + c.Assert(obj.Field.tag, Equals, item.tag) + c.Assert(obj.Field.value, DeepEquals, item.value) + } +} + +func (s *S) TestUnmarshalWithValueSetter(c *C) { + for _, item := range setterTests { + obj := &setterValueType{} + err := yaml.Unmarshal([]byte(item.data), obj) + c.Assert(err, IsNil) + c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value)) c.Assert(obj.Field.tag, Equals, item.tag) c.Assert(obj.Field.value, DeepEquals, item.value) }
diff --git a/encode.go b/encode.go index c700443..1d928b0 100644 --- a/encode.go +++ b/encode.go
@@ -4,6 +4,7 @@ "reflect" "sort" "strconv" + "time" ) type encoder struct { @@ -85,7 +86,11 @@ case reflect.String: e.stringv(tag, in) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - e.intv(tag, in) + if in.Type() == durationType { + e.stringv(tag, reflect.ValueOf(in.Interface().(time.Duration).String())) + } else { + e.intv(tag, in) + } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: e.uintv(tag, in) case reflect.Float32, reflect.Float64:
diff --git a/encode_test.go b/encode_test.go index 0ab65b9..c7461d5 100644 --- a/encode_test.go +++ b/encode_test.go
@@ -2,11 +2,12 @@ import ( "fmt" - . "launchpad.net/gocheck" "gopkg.in/yaml.v1" + . "gopkg.in/check.v1" "math" "strconv" "strings" + "time" ) var marshalIntTest = 123 @@ -212,6 +213,12 @@ }{1, inlineB{2, inlineC{3}}}, "a: 1\nb: 2\nc: 3\n", }, + + // Duration + { + map[string]time.Duration{"a": 3 * time.Second}, + "a: 3s\n", + }, } func (s *S) TestMarshal(c *C) {
diff --git a/suite_test.go b/suite_test.go index 111d756..c5cf1ed 100644 --- a/suite_test.go +++ b/suite_test.go
@@ -1,7 +1,7 @@ package yaml_test import ( - . "launchpad.net/gocheck" + . "gopkg.in/check.v1" "testing" )