Browse Source

Fix Setter handling on non-pointer fields.

Fixes #8.
Gustavo Niemeyer 12 years ago
parent
commit
41c132e8ac
2 changed files with 29 additions and 5 deletions
  1. 10 0
      decode.go
  2. 19 5
      decode_test.go

+ 10 - 0
decode.go

@@ -212,6 +212,16 @@ func newDecoder() *decoder {
 //   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

+ 19 - 5
decode_test.go

@@ -465,17 +465,31 @@ func (o *typeWithSetter) SetYAML(tag string, value interface{}) (ok bool) {
 	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 := &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.tag, Equals, item.tag)
+		c.Assert(obj.Field.value, DeepEquals, item.value)
+	}
+}
+
+func (s *S) TestUnmarshalWithValueSetter(c *C) {
 	for _, item := range setterTests {
-		obj := &typeWithSetterField{}
+		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, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
 		c.Assert(obj.Field.tag, Equals, item.tag)
 		c.Assert(obj.Field.value, DeepEquals, item.value)
 	}