diff --git a/genmethod.go b/genmethod.go index 855d70e..2bea522 100644 --- a/genmethod.go +++ b/genmethod.go @@ -108,17 +108,27 @@ func genMarshalJSON(mtyp *marshalerType) Function { // genUnmarshalYAML generates the UnmarshalYAML method. func genUnmarshalYAML(mtyp *marshalerType) Function { + return genUnmarshalLikeYAML(mtyp, "YAML") +} + +// genUnmarshalTOML generates the UnmarshalTOML method. +func genUnmarshalTOML(mtyp *marshalerType) Function { + return genUnmarshalLikeYAML(mtyp, "TOML") +} + +func genUnmarshalLikeYAML(mtyp *marshalerType, name string) Function { var ( m = newMarshalMethod(mtyp, true) recv = m.receiver() unmarshal = Name(m.scope.newIdent("unmarshal")) - intertyp = m.intermediateType(m.scope.newIdent(m.mtyp.orig.Obj().Name() + "YAML")) + intertyp = m.intermediateType(m.scope.newIdent(m.mtyp.orig.Obj().Name() + name)) dec = Name(m.scope.newIdent("dec")) conv = Name(m.scope.newIdent("x")) + tag = strings.ToLower(name) ) fn := Function{ Receiver: recv, - Name: "UnmarshalYAML", + Name: "Unmarshal" + name, ReturnTypes: Types{{TypeName: "error"}}, Parameters: Types{{Name: unmarshal.Name, TypeName: "func (interface{}) error"}}, Body: []Statement{ @@ -128,7 +138,7 @@ func genUnmarshalYAML(mtyp *marshalerType) Function { Declare{Name: conv.Name, TypeName: m.mtyp.name}, }, } - fn.Body = append(fn.Body, m.unmarshalConversions(dec, conv, "yaml")...) + fn.Body = append(fn.Body, m.unmarshalConversions(dec, conv, tag)...) fn.Body = append(fn.Body, Assign{Lhs: Star{Value: Name(recv.Name)}, Rhs: conv}) fn.Body = append(fn.Body, Return{Values: []Expression{NIL}}) return fn @@ -136,22 +146,32 @@ func genUnmarshalYAML(mtyp *marshalerType) Function { // genMarshalYAML generates the MarshalYAML method. func genMarshalYAML(mtyp *marshalerType) Function { + return genMarshalLikeYAML(mtyp, "YAML") +} + +// genMarshalTOML generates the MarshalTOML method. +func genMarshalTOML(mtyp *marshalerType) Function { + return genMarshalLikeYAML(mtyp, "TOML") +} + +func genMarshalLikeYAML(mtyp *marshalerType, name string) Function { var ( m = newMarshalMethod(mtyp, false) recv = m.receiver() - intertyp = m.intermediateType(m.scope.newIdent(m.mtyp.orig.Obj().Name() + "YAML")) + intertyp = m.intermediateType(m.scope.newIdent(m.mtyp.orig.Obj().Name() + name)) enc = Name(m.scope.newIdent("enc")) + tag = strings.ToLower(name) ) fn := Function{ Receiver: recv, - Name: "MarshalYAML", + Name: "Marshal" + name, ReturnTypes: Types{{TypeName: "interface{}"}, {TypeName: "error"}}, Body: []Statement{ declStmt{intertyp}, Declare{Name: enc.Name, TypeName: intertyp.Name}, }, } - fn.Body = append(fn.Body, m.marshalConversions(Name(recv.Name), enc, "yaml")...) + fn.Body = append(fn.Body, m.marshalConversions(Name(recv.Name), enc, tag)...) fn.Body = append(fn.Body, Return{Values: []Expression{AddressOf{Value: enc}, NIL}}) return fn } diff --git a/internal/tests/mapconv/input.go b/internal/tests/mapconv/input.go index 64907c7..89d4d49 100644 --- a/internal/tests/mapconv/input.go +++ b/internal/tests/mapconv/input.go @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license, // which can be found in the LICENSE file. -//go:generate gencodec -type X -field-override Xo -formats json,yaml -out output.go +//go:generate gencodec -type X -field-override Xo -formats json,yaml,toml -out output.go package mapconv diff --git a/internal/tests/mapconv/output.go b/internal/tests/mapconv/output.go index 762ec71..316753b 100644 --- a/internal/tests/mapconv/output.go +++ b/internal/tests/mapconv/output.go @@ -132,3 +132,66 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error { *x = x0 return nil } + +func (x X) MarshalTOML() (interface{}, error) { + type XTOML struct { + Map map[replacedString]replacedInt + Named namedMap2 + NoConv map[string]int + NoConvNamed namedMap + } + var enc XTOML + if x.Map != nil { + enc.Map = make(map[replacedString]replacedInt, len(x.Map)) + for k, v := range x.Map { + enc.Map[replacedString(k)] = replacedInt(v) + } + } + if x.Named != nil { + enc.Named = make(namedMap2, len(x.Named)) + for k, v := range x.Named { + enc.Named[replacedString(k)] = replacedInt(v) + } + } + enc.NoConv = x.NoConv + enc.NoConvNamed = x.NoConvNamed + return &enc, nil +} + +func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error { + type XTOML struct { + Map map[replacedString]replacedInt + Named namedMap2 + NoConv map[string]int + NoConvNamed namedMap + } + var dec XTOML + if err := unmarshal(&dec); err != nil { + return err + } + var x0 X + if dec.Map == nil { + return errors.New("missing required field 'map' for X") + } + x0.Map = make(map[string]int, len(dec.Map)) + for k, v := range dec.Map { + x0.Map[string(k)] = int(v) + } + if dec.Named == nil { + return errors.New("missing required field 'named' for X") + } + x0.Named = make(namedMap, len(dec.Named)) + for k, v := range dec.Named { + x0.Named[string(k)] = int(v) + } + if dec.NoConv == nil { + return errors.New("missing required field 'noConv' for X") + } + x0.NoConv = dec.NoConv + if dec.NoConvNamed == nil { + return errors.New("missing required field 'noConvNamed' for X") + } + x0.NoConvNamed = dec.NoConvNamed + *x = x0 + return nil +} diff --git a/internal/tests/nameclash/input.go b/internal/tests/nameclash/input.go index 81a239b..623fe40 100644 --- a/internal/tests/nameclash/input.go +++ b/internal/tests/nameclash/input.go @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license, // which can be found in the LICENSE file. -//go:generate gencodec -type Y -field-override Yo -formats json,yaml -out output.go +//go:generate gencodec -type Y -field-override Yo -formats json,yaml,toml -out output.go package nameclash diff --git a/internal/tests/nameclash/output.go b/internal/tests/nameclash/output.go index 831cb49..614c222 100644 --- a/internal/tests/nameclash/output.go +++ b/internal/tests/nameclash/output.go @@ -106,3 +106,52 @@ func (y *Y) UnmarshalYAML(unmarshal func(interface{}) error) error { *y = x return nil } + +func (y Y) MarshalTOML() (interface{}, error) { + type YTOML struct { + Foo json0.Foo `optional:"true"` + Foo2 json0.Foo `optional:"true"` + Bar errors0.Foo `optional:"true"` + Gazonk YJSON `optional:"true"` + Over enc `optional:"true"` + } + var enc0 YTOML + enc0.Foo = y.Foo + enc0.Foo2 = y.Foo2 + enc0.Bar = y.Bar + enc0.Gazonk = y.Gazonk + enc0.Over = enc(y.Over) + return &enc0, nil +} + +func (y *Y) UnmarshalTOML(unmarshal func(interface{}) error) error { + type YTOML struct { + Foo *json0.Foo `optional:"true"` + Foo2 *json0.Foo `optional:"true"` + Bar *errors0.Foo `optional:"true"` + Gazonk *YJSON `optional:"true"` + Over *enc `optional:"true"` + } + var dec YTOML + if err := unmarshal(&dec); err != nil { + return err + } + var x Y + if dec.Foo != nil { + x.Foo = *dec.Foo + } + if dec.Foo2 != nil { + x.Foo2 = *dec.Foo2 + } + if dec.Bar != nil { + x.Bar = *dec.Bar + } + if dec.Gazonk != nil { + x.Gazonk = *dec.Gazonk + } + if dec.Over != nil { + x.Over = int(*dec.Over) + } + *y = x + return nil +} diff --git a/internal/tests/omitempty/input.go b/internal/tests/omitempty/input.go index 0fc8fef..b41659c 100644 --- a/internal/tests/omitempty/input.go +++ b/internal/tests/omitempty/input.go @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license, // which can be found in the LICENSE file. -//go:generate gencodec -type X -field-override Xo -formats json,yaml -out output.go +//go:generate gencodec -type X -field-override Xo -formats json,yaml,toml -out output.go package omitempty diff --git a/internal/tests/omitempty/output.go b/internal/tests/omitempty/output.go index cf6148f..7c7f8c5 100644 --- a/internal/tests/omitempty/output.go +++ b/internal/tests/omitempty/output.go @@ -58,3 +58,29 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error { *x = x0 return nil } + +func (x X) MarshalTOML() (interface{}, error) { + type XTOML struct { + Int replacedInt `json:",omitempty"` + } + var enc XTOML + enc.Int = replacedInt(x.Int) + return &enc, nil +} + +func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error { + type XTOML struct { + Int *replacedInt `json:",omitempty"` + } + var dec XTOML + if err := unmarshal(&dec); err != nil { + return err + } + var x0 X + if dec.Int == nil { + return errors.New("missing required field 'int' for X") + } + x0.Int = int(*dec.Int) + *x = x0 + return nil +} diff --git a/internal/tests/sliceconv/input.go b/internal/tests/sliceconv/input.go index b990d5a..7b59f4d 100644 --- a/internal/tests/sliceconv/input.go +++ b/internal/tests/sliceconv/input.go @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license, // which can be found in the LICENSE file. -//go:generate gencodec -type X -field-override Xo -formats json,yaml -out output.go +//go:generate gencodec -type X -field-override Xo -formats json,yaml,toml -out output.go package sliceconv diff --git a/internal/tests/sliceconv/output.go b/internal/tests/sliceconv/output.go index 63bfaf1..47417d8 100644 --- a/internal/tests/sliceconv/output.go +++ b/internal/tests/sliceconv/output.go @@ -146,3 +146,73 @@ func (x *X) UnmarshalYAML(unmarshal func(interface{}) error) error { *x = x0 return nil } + +func (x X) MarshalTOML() (interface{}, error) { + type XTOML struct { + Slice []replacedInt + Named namedSlice2 + ByteString []byte + NoConv []int + NoConvNamed namedSlice + } + var enc XTOML + if x.Slice != nil { + enc.Slice = make([]replacedInt, len(x.Slice)) + for k, v := range x.Slice { + enc.Slice[k] = replacedInt(v) + } + } + if x.Named != nil { + enc.Named = make(namedSlice2, len(x.Named)) + for k, v := range x.Named { + enc.Named[k] = replacedInt(v) + } + } + enc.ByteString = []byte(x.ByteString) + enc.NoConv = x.NoConv + enc.NoConvNamed = x.NoConvNamed + return &enc, nil +} + +func (x *X) UnmarshalTOML(unmarshal func(interface{}) error) error { + type XTOML struct { + Slice []replacedInt + Named namedSlice2 + ByteString []byte + NoConv []int + NoConvNamed namedSlice + } + var dec XTOML + if err := unmarshal(&dec); err != nil { + return err + } + var x0 X + if dec.Slice == nil { + return errors.New("missing required field 'slice' for X") + } + x0.Slice = make([]int, len(dec.Slice)) + for k, v := range dec.Slice { + x0.Slice[k] = int(v) + } + if dec.Named == nil { + return errors.New("missing required field 'named' for X") + } + x0.Named = make(namedSlice, len(dec.Named)) + for k, v := range dec.Named { + x0.Named[k] = int(v) + } + if dec.ByteString == nil { + return errors.New("missing required field 'byteString' for X") + } + x0.ByteString = string(dec.ByteString) + if dec.NoConv == nil { + return errors.New("missing required field 'noConv' for X") + } + x0.NoConv = dec.NoConv + if dec.NoConvNamed == nil { + return errors.New("missing required field 'noConvNamed' for X") + } + x0.NoConvNamed = dec.NoConvNamed + *x = x0 + return nil +} diff --git a/main.go b/main.go index 2bdecff..d0aa6b8 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,7 @@ Command gencodec generates marshaling methods for struct types. When gencodec is invoked on a directory and type name, it creates a Go source file -containing JSON and YAML marshaling methods for the type. The generated methods add +containing JSON, YAML and TOML marshaling methods for the type. The generated methods add features which the standard json package cannot offer. gencodec -type MyType -out mytype_json.go @@ -148,7 +148,7 @@ func fatal(args ...interface{}) { os.Exit(1) } -var AllFormats = []string{"json", "yaml"} +var AllFormats = []string{"json", "yaml", "toml"} type Config struct { Dir string // input package directory @@ -241,6 +241,10 @@ func generate(mtyp *marshalerType, cfg *Config) ([]byte, error) { writeFunction(w, mtyp.fs, genMarshalYAML(mtyp)) fmt.Fprintln(w) writeFunction(w, mtyp.fs, genUnmarshalYAML(mtyp)) + case "toml": + writeFunction(w, mtyp.fs, genMarshalTOML(mtyp)) + fmt.Fprintln(w) + writeFunction(w, mtyp.fs, genUnmarshalTOML(mtyp)) default: return nil, fmt.Errorf("unknown format: %q", format) }