don't reset all fields in Unmarshal*

This preserves decoding into a struct with pre-filled, possibly
unexported fields.
master
Felix Lange 8 years ago
parent b2a8c619f3
commit faf3ce92a4
  1. 10
      genmethod.go
  2. 28
      internal/tests/mapconv/output.go
  3. 24
      internal/tests/nameclash/output.go
  4. 8
      internal/tests/omitempty/output.go
  5. 32
      internal/tests/sliceconv/output.go

@ -54,7 +54,6 @@ func genUnmarshalJSON(mtyp *marshalerType) Function {
input = Name(m.scope.newIdent("input")) input = Name(m.scope.newIdent("input"))
intertyp = m.intermediateType(m.scope.newIdent(m.mtyp.orig.Obj().Name() + "JSON")) intertyp = m.intermediateType(m.scope.newIdent(m.mtyp.orig.Obj().Name() + "JSON"))
dec = Name(m.scope.newIdent("dec")) dec = Name(m.scope.newIdent("dec"))
conv = Name(m.scope.newIdent("x"))
json = Name(m.scope.parent.packageName("encoding/json")) json = Name(m.scope.parent.packageName("encoding/json"))
) )
fn := Function{ fn := Function{
@ -69,11 +68,9 @@ func genUnmarshalJSON(mtyp *marshalerType) Function {
Func: Dotted{Receiver: json, Name: "Unmarshal"}, Func: Dotted{Receiver: json, Name: "Unmarshal"},
Params: []Expression{input, AddressOf{Value: dec}}, Params: []Expression{input, AddressOf{Value: dec}},
}), }),
Declare{Name: conv.Name, TypeName: m.mtyp.name},
}, },
} }
fn.Body = append(fn.Body, m.unmarshalConversions(dec, conv, "json")...) fn.Body = append(fn.Body, m.unmarshalConversions(dec, Name(recv.Name), "json")...)
fn.Body = append(fn.Body, Assign{Lhs: Star{Value: Name(recv.Name)}, Rhs: conv})
fn.Body = append(fn.Body, Return{Values: []Expression{NIL}}) fn.Body = append(fn.Body, Return{Values: []Expression{NIL}})
return fn return fn
} }
@ -123,7 +120,6 @@ func genUnmarshalLikeYAML(mtyp *marshalerType, name string) Function {
unmarshal = Name(m.scope.newIdent("unmarshal")) unmarshal = Name(m.scope.newIdent("unmarshal"))
intertyp = m.intermediateType(m.scope.newIdent(m.mtyp.orig.Obj().Name() + name)) intertyp = m.intermediateType(m.scope.newIdent(m.mtyp.orig.Obj().Name() + name))
dec = Name(m.scope.newIdent("dec")) dec = Name(m.scope.newIdent("dec"))
conv = Name(m.scope.newIdent("x"))
tag = strings.ToLower(name) tag = strings.ToLower(name)
) )
fn := Function{ fn := Function{
@ -135,11 +131,9 @@ func genUnmarshalLikeYAML(mtyp *marshalerType, name string) Function {
declStmt{intertyp}, declStmt{intertyp},
Declare{Name: dec.Name, TypeName: intertyp.Name}, Declare{Name: dec.Name, TypeName: intertyp.Name},
errCheck(CallFunction{Func: unmarshal, Params: []Expression{AddressOf{Value: dec}}}), errCheck(CallFunction{Func: unmarshal, Params: []Expression{AddressOf{Value: dec}}}),
Declare{Name: conv.Name, TypeName: m.mtyp.name},
}, },
} }
fn.Body = append(fn.Body, m.unmarshalConversions(dec, conv, tag)...) fn.Body = append(fn.Body, m.unmarshalConversions(dec, Name(recv.Name), tag)...)
fn.Body = append(fn.Body, Assign{Lhs: Star{Value: Name(recv.Name)}, Rhs: conv})
fn.Body = append(fn.Body, Return{Values: []Expression{NIL}}) fn.Body = append(fn.Body, Return{Values: []Expression{NIL}})
return fn return fn
} }

@ -106,30 +106,28 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
return err return err
} }
var x0 X
if dec.Map == nil { if dec.Map == nil {
return errors.New("missing required field 'map' for X") return errors.New("missing required field 'map' for X")
} }
x0.Map = make(map[string]int, len(dec.Map)) x.Map = make(map[string]int, len(dec.Map))
for k, v := range dec.Map { for k, v := range dec.Map {
x0.Map[string(k)] = int(v) x.Map[string(k)] = int(v)
} }
if dec.Named == nil { if dec.Named == nil {
return errors.New("missing required field 'named' for X") return errors.New("missing required field 'named' for X")
} }
x0.Named = make(namedMap, len(dec.Named)) x.Named = make(namedMap, len(dec.Named))
for k, v := range dec.Named { for k, v := range dec.Named {
x0.Named[string(k)] = int(v) x.Named[string(k)] = int(v)
} }
if dec.NoConv == nil { if dec.NoConv == nil {
return errors.New("missing required field 'noConv' for X") return errors.New("missing required field 'noConv' for X")
} }
x0.NoConv = dec.NoConv x.NoConv = dec.NoConv
if dec.NoConvNamed == nil { if dec.NoConvNamed == nil {
return errors.New("missing required field 'noConvNamed' for X") return errors.New("missing required field 'noConvNamed' for X")
} }
x0.NoConvNamed = dec.NoConvNamed x.NoConvNamed = dec.NoConvNamed
*x = x0
return nil return nil
} }
@ -169,29 +167,27 @@ func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
return err return err
} }
var x0 X
if dec.Map == nil { if dec.Map == nil {
return errors.New("missing required field 'map' for X") return errors.New("missing required field 'map' for X")
} }
x0.Map = make(map[string]int, len(dec.Map)) x.Map = make(map[string]int, len(dec.Map))
for k, v := range dec.Map { for k, v := range dec.Map {
x0.Map[string(k)] = int(v) x.Map[string(k)] = int(v)
} }
if dec.Named == nil { if dec.Named == nil {
return errors.New("missing required field 'named' for X") return errors.New("missing required field 'named' for X")
} }
x0.Named = make(namedMap, len(dec.Named)) x.Named = make(namedMap, len(dec.Named))
for k, v := range dec.Named { for k, v := range dec.Named {
x0.Named[string(k)] = int(v) x.Named[string(k)] = int(v)
} }
if dec.NoConv == nil { if dec.NoConv == nil {
return errors.New("missing required field 'noConv' for X") return errors.New("missing required field 'noConv' for X")
} }
x0.NoConv = dec.NoConv x.NoConv = dec.NoConv
if dec.NoConvNamed == nil { if dec.NoConvNamed == nil {
return errors.New("missing required field 'noConvNamed' for X") return errors.New("missing required field 'noConvNamed' for X")
} }
x0.NoConvNamed = dec.NoConvNamed x.NoConvNamed = dec.NoConvNamed
*x = x0
return nil return nil
} }

@ -87,23 +87,21 @@ func (y *Y) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
return err return err
} }
var x Y
if dec.Foo != nil { if dec.Foo != nil {
x.Foo = *dec.Foo y.Foo = *dec.Foo
} }
if dec.Foo2 != nil { if dec.Foo2 != nil {
x.Foo2 = *dec.Foo2 y.Foo2 = *dec.Foo2
} }
if dec.Bar != nil { if dec.Bar != nil {
x.Bar = *dec.Bar y.Bar = *dec.Bar
} }
if dec.Gazonk != nil { if dec.Gazonk != nil {
x.Gazonk = *dec.Gazonk y.Gazonk = *dec.Gazonk
} }
if dec.Over != nil { if dec.Over != nil {
x.Over = int(*dec.Over) y.Over = int(*dec.Over)
} }
*y = x
return nil return nil
} }
@ -136,22 +134,20 @@ func (y *Y) UnmarshalTOML(unmarshal func(interface{}) error) error {
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
return err return err
} }
var x Y
if dec.Foo != nil { if dec.Foo != nil {
x.Foo = *dec.Foo y.Foo = *dec.Foo
} }
if dec.Foo2 != nil { if dec.Foo2 != nil {
x.Foo2 = *dec.Foo2 y.Foo2 = *dec.Foo2
} }
if dec.Bar != nil { if dec.Bar != nil {
x.Bar = *dec.Bar y.Bar = *dec.Bar
} }
if dec.Gazonk != nil { if dec.Gazonk != nil {
x.Gazonk = *dec.Gazonk y.Gazonk = *dec.Gazonk
} }
if dec.Over != nil { if dec.Over != nil {
x.Over = int(*dec.Over) y.Over = int(*dec.Over)
} }
*y = x
return nil return nil
} }

@ -50,12 +50,10 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
return err return err
} }
var x0 X
if dec.Int == nil { if dec.Int == nil {
return errors.New("missing required field 'int' for X") return errors.New("missing required field 'int' for X")
} }
x0.Int = int(*dec.Int) x.Int = int(*dec.Int)
*x = x0
return nil return nil
} }
@ -76,11 +74,9 @@ func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
return err return err
} }
var x0 X
if dec.Int == nil { if dec.Int == nil {
return errors.New("missing required field 'int' for X") return errors.New("missing required field 'int' for X")
} }
x0.Int = int(*dec.Int) x.Int = int(*dec.Int)
*x = x0
return nil return nil
} }

@ -116,34 +116,32 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
return err return err
} }
var x0 X
if dec.Slice == nil { if dec.Slice == nil {
return errors.New("missing required field 'slice' for X") return errors.New("missing required field 'slice' for X")
} }
x0.Slice = make([]int, len(dec.Slice)) x.Slice = make([]int, len(dec.Slice))
for k, v := range dec.Slice { for k, v := range dec.Slice {
x0.Slice[k] = int(v) x.Slice[k] = int(v)
} }
if dec.Named == nil { if dec.Named == nil {
return errors.New("missing required field 'named' for X") return errors.New("missing required field 'named' for X")
} }
x0.Named = make(namedSlice, len(dec.Named)) x.Named = make(namedSlice, len(dec.Named))
for k, v := range dec.Named { for k, v := range dec.Named {
x0.Named[k] = int(v) x.Named[k] = int(v)
} }
if dec.ByteString == nil { if dec.ByteString == nil {
return errors.New("missing required field 'byteString' for X") return errors.New("missing required field 'byteString' for X")
} }
x0.ByteString = string(dec.ByteString) x.ByteString = string(dec.ByteString)
if dec.NoConv == nil { if dec.NoConv == nil {
return errors.New("missing required field 'noConv' for X") return errors.New("missing required field 'noConv' for X")
} }
x0.NoConv = dec.NoConv x.NoConv = dec.NoConv
if dec.NoConvNamed == nil { if dec.NoConvNamed == nil {
return errors.New("missing required field 'noConvNamed' for X") return errors.New("missing required field 'noConvNamed' for X")
} }
x0.NoConvNamed = dec.NoConvNamed x.NoConvNamed = dec.NoConvNamed
*x = x0
return nil return nil
} }
@ -186,33 +184,31 @@ func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error {
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
return err return err
} }
var x0 X
if dec.Slice == nil { if dec.Slice == nil {
return errors.New("missing required field 'slice' for X") return errors.New("missing required field 'slice' for X")
} }
x0.Slice = make([]int, len(dec.Slice)) x.Slice = make([]int, len(dec.Slice))
for k, v := range dec.Slice { for k, v := range dec.Slice {
x0.Slice[k] = int(v) x.Slice[k] = int(v)
} }
if dec.Named == nil { if dec.Named == nil {
return errors.New("missing required field 'named' for X") return errors.New("missing required field 'named' for X")
} }
x0.Named = make(namedSlice, len(dec.Named)) x.Named = make(namedSlice, len(dec.Named))
for k, v := range dec.Named { for k, v := range dec.Named {
x0.Named[k] = int(v) x.Named[k] = int(v)
} }
if dec.ByteString == nil { if dec.ByteString == nil {
return errors.New("missing required field 'byteString' for X") return errors.New("missing required field 'byteString' for X")
} }
x0.ByteString = string(dec.ByteString) x.ByteString = string(dec.ByteString)
if dec.NoConv == nil { if dec.NoConv == nil {
return errors.New("missing required field 'noConv' for X") return errors.New("missing required field 'noConv' for X")
} }
x0.NoConv = dec.NoConv x.NoConv = dec.NoConv
if dec.NoConvNamed == nil { if dec.NoConvNamed == nil {
return errors.New("missing required field 'noConvNamed' for X") return errors.New("missing required field 'noConvNamed' for X")
} }
x0.NoConvNamed = dec.NoConvNamed x.NoConvNamed = dec.NoConvNamed
*x = x0
return nil return nil
} }

Loading…
Cancel
Save