From 84cd251933007f78b08e9cec1c46c256df0b5925 Mon Sep 17 00:00:00 2001 From: Malte Isberner Date: Fri, 5 Aug 2022 21:24:07 -0700 Subject: [PATCH] allow using pointer receivers, always use pointers for passing structs for internally generated functions --- bootstrap/bootstrap.go | 12 ++++++++++-- easyjson/main.go | 2 ++ gen/encoder.go | 21 +++++++++++++++------ gen/generator.go | 6 ++++++ 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index 5755beea..1cfc982b 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -32,6 +32,7 @@ type Generator struct { OmitEmpty bool DisallowUnknownFields bool SkipMemberNameUnescaping bool + PtrReceivers bool OutName string BuildTags string @@ -69,15 +70,19 @@ func (g *Generator) writeStub() error { fmt.Fprintln(f, ")") } + inPtrPrefix := "" + if g.PtrReceivers { + inPtrPrefix = "*" + } sort.Strings(g.Types) for _, t := range g.Types { fmt.Fprintln(f) if !g.NoStdMarshalers { - fmt.Fprintln(f, "func (", t, ") MarshalJSON() ([]byte, error) { return nil, nil }") + fmt.Fprintln(f, "func (", inPtrPrefix, t, ") MarshalJSON() ([]byte, error) { return nil, nil }") fmt.Fprintln(f, "func (*", t, ") UnmarshalJSON([]byte) error { return nil }") } - fmt.Fprintln(f, "func (", t, ") MarshalEasyJSON(w *jwriter.Writer) {}") + fmt.Fprintln(f, "func (", inPtrPrefix, t, ") MarshalEasyJSON(w *jwriter.Writer) {}") fmt.Fprintln(f, "func (*", t, ") UnmarshalEasyJSON(l *jlexer.Lexer) {}") fmt.Fprintln(f) fmt.Fprintln(f, "type EasyJSON_exporter_"+t+" *"+t) @@ -137,6 +142,9 @@ func (g *Generator) writeMain() (path string, err error) { if g.SkipMemberNameUnescaping { fmt.Fprintln(f, " g.SkipMemberNameUnescaping()") } + if g.PtrReceivers { + fmt.Fprintln(f, " g.PtrReceivers()") + } sort.Strings(g.Types) for _, v := range g.Types { diff --git a/easyjson/main.go b/easyjson/main.go index d337c846..1153c5c1 100644 --- a/easyjson/main.go +++ b/easyjson/main.go @@ -31,6 +31,7 @@ var specifiedName = flag.String("output_filename", "", "specify the filename of var processPkg = flag.Bool("pkg", false, "process the whole package instead of just the given file") var disallowUnknownFields = flag.Bool("disallow_unknown_fields", false, "return error if any unknown field in json appeared") var skipMemberNameUnescaping = flag.Bool("disable_members_unescape", false, "don't perform unescaping of member names to improve performance") +var ptrReceivers = flag.Bool("ptr_receivers", false, "use pointer receivers for all generated marshaling methods") func generate(fname string) (err error) { fInfo, err := os.Stat(fname) @@ -85,6 +86,7 @@ func generate(fname string) (err error) { StubsOnly: *stubs, NoFormat: *noformat, SimpleBytes: *simpleBytes, + PtrReceivers: *ptrReceivers, } if err := g.Run(); err != nil { diff --git a/gen/encoder.go b/gen/encoder.go index ed6d6ad5..d188bb94 100644 --- a/gen/encoder.go +++ b/gen/encoder.go @@ -203,7 +203,7 @@ func (g *Generator) genTypeEncoderNoCheck(t reflect.Type, in string, tags fieldT enc := g.getEncoderName(t) g.addType(t) - fmt.Fprintln(g.out, ws+enc+"(out, "+in+")") + fmt.Fprintln(g.out, ws+enc+"(out, &"+in+")") case reflect.Ptr: if !assumeNonEmpty { @@ -406,7 +406,7 @@ func (g *Generator) genStructEncoder(t reflect.Type) error { fname := g.getEncoderName(t) typ := g.getType(t) - fmt.Fprintln(g.out, "func "+fname+"(out *jwriter.Writer, in "+typ+") {") + fmt.Fprintln(g.out, "func "+fname+"(out *jwriter.Writer, in *"+typ+") {") fmt.Fprintln(g.out, " out.RawByte('{')") fmt.Fprintln(g.out, " first := true") fmt.Fprintln(g.out, " _ = first") @@ -449,18 +449,27 @@ func (g *Generator) genStructMarshaler(t reflect.Type) error { fname := g.getEncoderName(t) typ := g.getType(t) + ptrPrefix := "" + addrOfPrefix := "" + if t.Kind() == reflect.Struct { + if g.ptrReceivers { + ptrPrefix = "*" + } else { + addrOfPrefix = "&" + } + } if !g.noStdMarshalers { fmt.Fprintln(g.out, "// MarshalJSON supports json.Marshaler interface") - fmt.Fprintln(g.out, "func (v "+typ+") MarshalJSON() ([]byte, error) {") + fmt.Fprintln(g.out, "func (v "+ptrPrefix+typ+") MarshalJSON() ([]byte, error) {") fmt.Fprintln(g.out, " w := jwriter.Writer{}") - fmt.Fprintln(g.out, " "+fname+"(&w, v)") + fmt.Fprintln(g.out, " "+fname+"(&w, "+addrOfPrefix+"v)") fmt.Fprintln(g.out, " return w.Buffer.BuildBytes(), w.Error") fmt.Fprintln(g.out, "}") } fmt.Fprintln(g.out, "// MarshalEasyJSON supports easyjson.Marshaler interface") - fmt.Fprintln(g.out, "func (v "+typ+") MarshalEasyJSON(w *jwriter.Writer) {") - fmt.Fprintln(g.out, " "+fname+"(w, v)") + fmt.Fprintln(g.out, "func (v "+ptrPrefix+typ+") MarshalEasyJSON(w *jwriter.Writer) {") + fmt.Fprintln(g.out, " "+fname+"(w, "+addrOfPrefix+"v)") fmt.Fprintln(g.out, "}") return nil diff --git a/gen/generator.go b/gen/generator.go index 79f4d6f7..59510157 100644 --- a/gen/generator.go +++ b/gen/generator.go @@ -39,6 +39,7 @@ type Generator struct { fieldNamer FieldNamer simpleBytes bool skipMemberNameUnescaping bool + ptrReceivers bool // package path to local alias map for tracking imports imports map[string]string @@ -123,6 +124,11 @@ func (g *Generator) SkipMemberNameUnescaping() { g.skipMemberNameUnescaping = true } +// PtrReceivers instructs to use pointer receivers for marshaling methods of structs. +func (g *Generator) PtrReceivers() { + g.ptrReceivers = true +} + // OmitEmpty triggers `json=",omitempty"` behaviour by default. func (g *Generator) OmitEmpty() { g.omitEmpty = true