github.com/ronaksoft/rony@v0.16.26-0.20230807065236-1743dbfe6959/cmd/protoc-gen-gorony/helper/gen.go (about) 1 package helper 2 3 import ( 4 "fmt" 5 "strings" 6 "text/template" 7 8 "github.com/ronaksoft/rony/internal/codegen" 9 "google.golang.org/protobuf/compiler/protogen" 10 ) 11 12 /* 13 Creation Time: 2021 - Mar - 02 14 Created by: (ehsan) 15 Maintainers: 16 1. Ehsan N. Moosa (E2) 17 Auditor: Ehsan N. Moosa (E2) 18 Copyright Ronak Software Group 2020 19 */ 20 21 func GenFunc(g *protogen.GeneratedFile, opt *codegen.PluginOptions, files ...*protogen.File) error { 22 initBlock := &strings.Builder{} 23 appendToInit := func(x string) { 24 initBlock.WriteString(x) 25 initBlock.WriteRune('\n') 26 } 27 g.P("package ", files[0].GoPackageName) 28 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: "sync"}) 29 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: "github.com/ronaksoft/rony/registry"}) 30 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: "google.golang.org/protobuf/proto"}) 31 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: "google.golang.org/protobuf/encoding/protojson"}) 32 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: "github.com/ronaksoft/rony/pools"}) 33 if !opt.NoEdgeDependency { 34 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: "github.com/ronaksoft/rony/edge"}) 35 } 36 37 g.P("var _ = pools.Imported") 38 for _, f := range files { 39 templateArg := codegen.GenTemplateArg(f) 40 for _, arg := range templateArg.Messages { 41 for _, f := range arg.Fields { 42 if f.Pkg() != "" { 43 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: f.ImportPath}) 44 } 45 } 46 appendToInit(fmt.Sprintf("registry.Register(%d, %q, factory%s)", arg.C, arg.Name(), arg.Name())) 47 g.P(codegen.ExecTemplate(template.Must(template.New("genPool").Parse(genPool)), arg)) 48 g.P(codegen.ExecTemplate(template.Must(template.New("genDeepCopy").Parse(genDeepCopy)), arg)) 49 g.P(codegen.ExecTemplate(template.Must(template.New("genClone").Parse(genClone)), arg)) 50 g.P(codegen.ExecTemplate(template.Must(template.New("genSerializers").Parse(genSerializers)), arg)) 51 if arg.IsEnvelope() { 52 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: "github.com/goccy/go-json"}) 53 } 54 g.P(codegen.ExecTemplate(template.Must(template.New("genFactory").Parse(genFactory)), arg)) 55 56 if !opt.NoEdgeDependency { 57 g.P(codegen.ExecTemplate(template.Must(template.New("genPushToContext").Parse(genPushToContext)), arg)) 58 } 59 } 60 for _, arg := range templateArg.Services { 61 for _, m := range arg.Methods { 62 if m.Output.Pkg() != "" { 63 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: m.Output.ImportPath}) 64 } 65 if m.Input.Pkg() != "" { 66 g.QualifiedGoIdent(protogen.GoIdent{GoName: "", GoImportPath: m.Input.ImportPath}) 67 } 68 appendToInit(fmt.Sprintf("registry.Register(%d, %q, factory%s)", m.C, m.Fullname(), m.Input.Name())) 69 g.P("const C_", m.Fullname(), " uint64 = ", fmt.Sprintf("%d", m.C)) 70 } 71 } 72 73 if initBlock.Len() > 0 { 74 g.P("// register constructors of the messages to the registry package") 75 g.P("func init() {") 76 g.P(initBlock.String()) 77 g.P("}") 78 } 79 } 80 81 return nil 82 } 83 84 const genPool = ` 85 const C_{{.Name}} uint64 = {{.C}} 86 type pool{{.Name}} struct { 87 pool sync.Pool 88 } 89 90 func (p *pool{{.Name}}) Get() *{{.Name}} { 91 x, ok := p.pool.Get().(*{{.Name}}) 92 if !ok { 93 x = &{{.Name}}{} 94 } 95 {{ range .Fields }} 96 {{- if and (eq .Cardinality "optional") (eq .Kind "message") }} 97 {{- if ne .Pkg ""}} 98 x.{{.Name}} = {{.Pkg}}.Pool{{.Type}}.Get() 99 {{- else}} 100 x.{{.Name}} = Pool{{.Type}}.Get() 101 {{- end}} 102 {{- end }} 103 {{ end }} 104 return x 105 } 106 107 func (p *pool{{.Name}}) Put(x *{{.Name}}) { 108 if x == nil { 109 return 110 } 111 112 {{ range .Fields }} 113 {{- if eq .Cardinality "repeated" }} 114 {{- if eq .Kind "message" }} 115 for _, z := range x.{{.Name}} { 116 {{- if ne .Pkg ""}} 117 {{.Pkg}}.Pool{{.Type}}.Put(z) 118 {{- else}} 119 Pool{{.Type}}.Put(z) 120 {{- end}} 121 } 122 x.{{.Name}} = x.{{.Name}}[:0] 123 {{- else if eq .Kind "bytes" }} 124 for _, z := range x.{{.Name}} { 125 pools.Bytes.Put(z) 126 } 127 x.{{.Name}} = x.{{.Name}}[:0] 128 {{- else }} 129 x.{{- .Name}} = x.{{.Name}}[:0] 130 {{- end }} 131 {{- else }} 132 {{- if eq .Kind "bytes" }} 133 x.{{.Name}} = x.{{.Name}}[:0] 134 {{- else if eq .Kind "message" }} 135 {{- if ne .Pkg ""}} 136 {{.Pkg}}.Pool{{.Type}}.Put(x.{{.Name}}) 137 {{- else}} 138 Pool{{.Type}}.Put(x.{{.Name}}) 139 {{- end}} 140 {{- else }} 141 x.{{.Name}} = {{.ZeroValue}} 142 {{- end }} 143 {{- end }} 144 {{- end }} 145 146 p.pool.Put(x) 147 } 148 149 var Pool{{.Name}} = pool{{.Name}}{} 150 ` 151 152 const genDeepCopy = ` 153 func (x *{{.Name}}) DeepCopy(z *{{.Name}}) { 154 {{- range .Fields -}} 155 {{- if eq .Cardinality "repeated" }} 156 {{- if eq .Kind "message" }} 157 for idx := range x.{{.Name}} { 158 if x.{{.Name}}[idx] == nil { 159 continue 160 } 161 {{- if eq .Pkg "" }} 162 xx := Pool{{.Type}}.Get() 163 {{- else }} 164 xx := {{.Pkg}}.Pool{{.Type}}.Get() 165 {{- end }} 166 x.{{.Name}}[idx].DeepCopy(xx) 167 z.{{.Name}} = append(z.{{.Name}}, xx) 168 } 169 {{- else if eq .Kind "bytes" }} 170 z.{{.Name}} = z.{{.Name}}[:0] 171 zl := len(z.{{.Name}}) 172 for idx := range x.{{.Name}} { 173 if idx < zl { 174 z.{{.Name}} = append(z.{{.Name}}, append(z.{{.Name}}[idx][:0], x.{{.Name}}[idx]...)) 175 } else { 176 zb := pools.Bytes.GetCap(len(x.{{.Name}}[idx])) 177 z.{{.Name}} = append(z.{{.Name}}, append(zb, x.{{.Name}}[idx]...)) 178 } 179 } 180 {{- else }} 181 z.{{.Name}} = append(z.{{.Name}}[:0], x.{{.Name}}...) 182 {{- end }} 183 {{- else }} 184 {{- if eq .Kind "message" }} 185 if x.{{.Name}} != nil { 186 if z.{{.Name}} == nil { 187 {{- if eq .Pkg "" }} 188 z.{{.Name}} = Pool{{.Type}}.Get() 189 {{- else }} 190 z.{{.Name}} = {{.Pkg}}.Pool{{.Type}}.Get() 191 {{- end }} 192 } 193 x.{{.Name}}.DeepCopy(z.{{.Name}}) 194 } else { 195 {{- if eq .Pkg "" }} 196 Pool{{.Type}}.Put(z.{{.Name}}) 197 {{- else }} 198 {{.Pkg}}.Pool{{.Type}}.Put(z.{{.Name}}) 199 {{- end }} 200 z.{{.Name}} = nil 201 } 202 {{- else if eq .Kind "bytes" }} 203 z.{{.Name}} = append(z.{{.Name}}[:0], x.{{.Name}}...) 204 {{- else }} 205 z.{{.Name}} = x.{{.Name}} 206 {{- end }} 207 {{- end }} 208 {{- end }} 209 } 210 211 ` 212 213 const genClone = ` 214 func (x *{{.Name}}) Clone() *{{.Name}} { 215 z := &{{.Name}}{} 216 x.DeepCopy(z) 217 return z 218 } 219 220 ` 221 222 const genPushToContext = ` 223 func (x *{{.Name}}) PushToContext(ctx *edge.RequestCtx) { 224 ctx.PushMessage({{.CName}}, x) 225 } 226 ` 227 228 const genSerializers = ` 229 func (x *{{.Name}}) Unmarshal(b []byte) error { 230 return proto.UnmarshalOptions{Merge: true}.Unmarshal(b, x) 231 } 232 233 func (x *{{.Name}}) Marshal() ([]byte, error) { 234 return proto.Marshal(x) 235 } 236 237 {{ if not .SkipJson }} 238 func (x *{{.Name}}) UnmarshalJSON(b []byte) error { 239 {{- if and .IsEnvelope }} 240 je := registry.JSONEnvelope{} 241 err := go_json.Unmarshal(b, &je) 242 if err != nil { 243 return err 244 } 245 246 x.Constructor = registry.N(je.Constructor) 247 248 m, err := registry.Get(x.Constructor) 249 if err != nil { 250 return err 251 } 252 253 err = m.UnmarshalJSON(je.Message) 254 if err != nil { 255 return err 256 } 257 258 x.Message, err = proto.Marshal(m) 259 if err != nil { 260 return err 261 } 262 263 return nil 264 {{- else }} 265 return protojson.Unmarshal(b, x) 266 {{- end }} 267 } 268 269 func (x *{{.Name}}) MarshalJSON() ([]byte, error) { 270 {{- if .IsEnvelope }} 271 m, err := registry.UnwrapJSON(x) 272 if err != nil { 273 return nil, err 274 } 275 276 je := registry.JSONEnvelope{ 277 Constructor: registry.C(x.Constructor), 278 } 279 280 je.Message, err = m.MarshalJSON() 281 if err != nil { 282 return nil, err 283 } 284 285 return go_json.Marshal(je) 286 {{- else }} 287 return protojson.Marshal(x) 288 {{- end }} 289 } 290 {{- end }} 291 ` 292 293 const genFactory = ` 294 func factory{{.Name}} () registry.Message { 295 return &{{.Name}}{} 296 } 297 `