diff options
Diffstat (limited to 'vendor/github.com/ugorji/go/codec/gen_mono.go')
| -rw-r--r-- | vendor/github.com/ugorji/go/codec/gen_mono.go | 586 |
1 files changed, 0 insertions, 586 deletions
diff --git a/vendor/github.com/ugorji/go/codec/gen_mono.go b/vendor/github.com/ugorji/go/codec/gen_mono.go deleted file mode 100644 index 841147863..000000000 --- a/vendor/github.com/ugorji/go/codec/gen_mono.go +++ /dev/null @@ -1,586 +0,0 @@ -// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a MIT license found in the LICENSE file. - -//go:build codec.build - -package codec - -import ( - "go/ast" - "go/format" - "go/parser" - "go/token" - "os" - "slices" - "strings" -) - -// This tool will monomorphize types scoped to a specific format. -// -// This tool only monomorphized the type Name, and not a function Name. -// Explicitly, generic functions are not supported, as they cannot be monomorphized -// to a specific format without a corresponding name change. -// -// However, for types constrained to encWriter or decReader, -// which are shared across formats, there's no place to put them without duplication. - -const genMonoParserMode = parser.AllErrors | parser.SkipObjectResolution - -var genMonoSpecialFieldTypes = []string{"helperDecReader"} - -// These functions should take the address of first param when monomorphized -var genMonoSpecialFunc4Addr = []string{} // {"decByteSlice"} - -var genMonoImportsToSkip = []string{`"errors"`, `"fmt"`, `"net/rpc"`} - -var genMonoRefImportsVia_ = [][2]string{ - // {"errors", "New"}, -} - -var genMonoCallsToSkip = []string{"callMake"} - -type genMonoFieldState uint - -const ( - genMonoFieldRecv genMonoFieldState = iota << 1 - genMonoFieldParamsResult - genMonoFieldStruct -) - -type genMonoImports struct { - set map[string]struct{} - specs []*ast.ImportSpec -} - -type genMono struct { - files map[string][]byte - typParam map[string]*ast.Field - typParamTransient map[string]*ast.Field -} - -func (x *genMono) init() { - x.files = make(map[string][]byte) - x.typParam = make(map[string]*ast.Field) - x.typParamTransient = make(map[string]*ast.Field) -} - -func (x *genMono) reset() { - clear(x.typParam) - clear(x.typParamTransient) -} - -func (m *genMono) hdl(hname string) { - m.reset() - m.do(hname, []string{"encode.go", "decode.go", hname + ".go"}, []string{"base.notfastpath.go", "base.notfastpath.notmono.go"}, "", "") - m.do(hname, []string{"base.notfastpath.notmono.go"}, nil, ".notfastpath", ` && (notfastpath || codec.notfastpath)`) - m.do(hname, []string{"base.fastpath.notmono.generated.go"}, []string{"base.fastpath.generated.go"}, ".fastpath", ` && !notfastpath && !codec.notfastpath`) -} - -func (m *genMono) do(hname string, fnames, tnames []string, fnameInfx string, buildTagsSfx string) { - // keep m.typParams across whole call, as all others use it - const fnameSfx = ".mono.generated.go" - fname := hname + fnameInfx + fnameSfx - - var imports = genMonoImports{set: make(map[string]struct{})} - - r1, fset := m.merge(fnames, tnames, &imports) - m.trFile(r1, hname, true) - - r2, fset := m.merge(fnames, tnames, &imports) - m.trFile(r2, hname, false) - - r0 := genMonoOutInit(imports.specs, fname) - r0.Decls = append(r0.Decls, r1.Decls...) - r0.Decls = append(r0.Decls, r2.Decls...) - - // output r1 to a file - f, err := os.Create(fname) - halt.onerror(err) - defer f.Close() - - var s genMonoStrBuilder - s.s(`//go:build !notmono && !codec.notmono `).s(buildTagsSfx).s(` - -// Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved. -// Use of this source code is governed by a MIT license found in the LICENSE file. - -`) - _, err = f.Write(s.v) - halt.onerror(err) - err = format.Node(f, fset, r0) - halt.onerror(err) -} - -func (x *genMono) file(fname string) (b []byte) { - b = x.files[fname] - if b == nil { - var err error - b, err = os.ReadFile(fname) - halt.onerror(err) - x.files[fname] = b - } - return -} - -func (x *genMono) merge(fNames, tNames []string, imports *genMonoImports) (dst *ast.File, fset *token.FileSet) { - // typParams used in fnLoadTyps - var typParams map[string]*ast.Field - var loadTyps bool - fnLoadTyps := func(node ast.Node) bool { - var ok bool - switch n := node.(type) { - case *ast.GenDecl: - if n.Tok == token.TYPE { - for _, v := range n.Specs { - nn := v.(*ast.TypeSpec) - ok = genMonoTypeParamsOk(nn.TypeParams) - if ok { - // each decl will have only 1 var/type - typParams[nn.Name.Name] = nn.TypeParams.List[0] - if loadTyps { - dst.Decls = append(dst.Decls, &ast.GenDecl{Tok: n.Tok, Specs: []ast.Spec{v}}) - } - } - } - } - return false - } - return true - } - - // we only merge top-level methods and types - fnIdX := func(n *ast.FuncDecl, n2 *ast.IndexExpr) (ok bool) { - n9, ok9 := n2.Index.(*ast.Ident) - n3, ok := n2.X.(*ast.Ident) // n3 = type name - ok = ok && ok9 && n9.Name == "T" - if ok { - _, ok = x.typParam[n3.Name] - } - return - } - - fnLoadMethodsAndImports := func(node ast.Node) bool { - var ok bool - switch n := node.(type) { - case *ast.FuncDecl: - // TypeParams is nil for methods, as it is defined at the type node - // instead, look at the name, and - // if IndexExpr.Index=T, and IndexExpr.X matches a type name seen already - // then ok = true - if n.Recv == nil || len(n.Recv.List) != 1 { - return false - } - ok = false - switch nn := n.Recv.List[0].Type.(type) { - case *ast.IndexExpr: - ok = fnIdX(n, nn) - case *ast.StarExpr: - switch nn2 := nn.X.(type) { - case *ast.IndexExpr: - ok = fnIdX(n, nn2) - } - } - if ok { - dst.Decls = append(dst.Decls, n) - } - return false - case *ast.GenDecl: - if n.Tok == token.IMPORT { - for _, v := range n.Specs { - nn := v.(*ast.ImportSpec) - if slices.Contains(genMonoImportsToSkip, nn.Path.Value) { - continue - } - if _, ok = imports.set[nn.Path.Value]; !ok { - imports.specs = append(imports.specs, nn) - imports.set[nn.Path.Value] = struct{}{} - } - } - } - return false - } - return true - } - - fset = token.NewFileSet() - fnLoadAsts := func(names []string) (asts []*ast.File) { - for _, fname := range names { - fsrc := x.file(fname) - f, err := parser.ParseFile(fset, fname, fsrc, genMonoParserMode) - halt.onerror(err) - asts = append(asts, f) - } - return - } - - clear(x.typParamTransient) - - dst = &ast.File{ - Name: &ast.Ident{Name: "codec"}, - } - - fs := fnLoadAsts(fNames) - ts := fnLoadAsts(tNames) - - loadTyps = true - typParams = x.typParam - for _, v := range fs { - ast.Inspect(v, fnLoadTyps) - } - loadTyps = false - typParams = x.typParamTransient - for _, v := range ts { - ast.Inspect(v, fnLoadTyps) - } - typParams = nil - for _, v := range fs { - ast.Inspect(v, fnLoadMethodsAndImports) - } - - return -} - -func (x *genMono) trFile(r *ast.File, hname string, isbytes bool) { - fn := func(node ast.Node) bool { - switch n := node.(type) { - case *ast.TypeSpec: - // type x[T encDriver] struct { ... } - if !genMonoTypeParamsOk(n.TypeParams) { - return false - } - x.trType(n, hname, isbytes) - return false - case *ast.FuncDecl: - if n.Recv == nil || len(n.Recv.List) != 1 { - return false - } - if _, ok := n.Recv.List[0].Type.(*ast.Ident); ok { - return false - } - tp := x.trMethodSign(n, hname, isbytes) // receiver, params, results - // handle the body - x.trMethodBody(n.Body, tp, hname, isbytes) - return false - } - return true - } - ast.Inspect(r, fn) - - // set type params to nil, and Pos to NoPos - fn = func(node ast.Node) bool { - switch n := node.(type) { - case *ast.FuncType: - if genMonoTypeParamsOk(n.TypeParams) { - n.TypeParams = nil - } - case *ast.TypeSpec: // for type ... - if genMonoTypeParamsOk(n.TypeParams) { - n.TypeParams = nil - } - } - return true - } - ast.Inspect(r, fn) -} - -func (x *genMono) trType(n *ast.TypeSpec, hname string, isbytes bool) { - sfx, _, _, hnameUp := genMonoIsBytesVals(hname, isbytes) - tp := n.TypeParams.List[0] - switch tp.Type.(*ast.Ident).Name { - case "encDriver", "decDriver": - n.Name.Name += hnameUp + sfx - case "encWriter", "decReader": - n.Name.Name += sfx - } - - // handle the Struct and Array types - switch nn := n.Type.(type) { - case *ast.StructType: - x.trStruct(nn, tp, hname, isbytes) - case *ast.ArrayType: - x.trArray(nn, tp, hname, isbytes) - } -} - -func (x *genMono) trMethodSign(n *ast.FuncDecl, hname string, isbytes bool) (tp *ast.Field) { - // check if recv type is not parameterized - tp = x.trField(n.Recv.List[0], nil, hname, isbytes, genMonoFieldRecv) - // handle params and results - x.trMethodSignNonRecv(n.Type.Params, tp, hname, isbytes) - x.trMethodSignNonRecv(n.Type.Results, tp, hname, isbytes) - return -} - -func (x *genMono) trMethodSignNonRecv(r *ast.FieldList, tp *ast.Field, hname string, isbytes bool) { - if r == nil || len(r.List) == 0 { - return - } - for _, v := range r.List { - x.trField(v, tp, hname, isbytes, genMonoFieldParamsResult) - } -} - -func (x *genMono) trStruct(r *ast.StructType, tp *ast.Field, hname string, isbytes bool) { - // search for fields, and update accordingly - // type x[T encDriver] struct { w T } - // var x *A[T] - // A[T] - if r == nil || r.Fields == nil || len(r.Fields.List) == 0 { - return - } - for _, v := range r.Fields.List { - x.trField(v, tp, hname, isbytes, genMonoFieldStruct) - } -} - -func (x *genMono) trArray(n *ast.ArrayType, tp *ast.Field, hname string, isbytes bool) { - sfx, _, _, hnameUp := genMonoIsBytesVals(hname, isbytes) - // type fastpathEs[T encDriver] [56]fastpathE[T] - // p := tp.Names[0].Name - switch elt := n.Elt.(type) { - // case *ast.InterfaceType: - case *ast.IndexExpr: - if elt.Index.(*ast.Ident).Name == "T" { // generic - n.Elt = ast.NewIdent(elt.X.(*ast.Ident).Name + hnameUp + sfx) - } - } -} - -func (x *genMono) trMethodBody(r *ast.BlockStmt, tp *ast.Field, hname string, isbytes bool) { - // find the parent node for an indexExpr, or a T/*T, and set the value back in there - - fn := func(pnode ast.Node) bool { - var pn *ast.Ident - fnUp := func() { - x.updateIdentForT(pn, hname, tp, isbytes, false) - } - switch n := pnode.(type) { - // case *ast.SelectorExpr: - // case *ast.TypeAssertExpr: - // case *ast.IndexExpr: - case *ast.StarExpr: - if genMonoUpdateIndexExprT(&pn, n.X) { - n.X = pn - fnUp() - } - case *ast.CallExpr: - for i4, n4 := range n.Args { - if genMonoUpdateIndexExprT(&pn, n4) { - n.Args[i4] = pn - fnUp() - } - } - if n4, ok4 := n.Fun.(*ast.Ident); ok4 && slices.Contains(genMonoSpecialFunc4Addr, n4.Name) { - n.Args[0] = &ast.UnaryExpr{Op: token.AND, X: n.Args[0].(*ast.SelectorExpr)} - } - case *ast.CompositeLit: - if genMonoUpdateIndexExprT(&pn, n.Type) { - n.Type = pn - fnUp() - } - case *ast.ArrayType: - if genMonoUpdateIndexExprT(&pn, n.Elt) { - n.Elt = pn - fnUp() - } - case *ast.ValueSpec: - for i2, n2 := range n.Values { - if genMonoUpdateIndexExprT(&pn, n2) { - n.Values[i2] = pn - fnUp() - } - } - if genMonoUpdateIndexExprT(&pn, n.Type) { - n.Type = pn - fnUp() - } - case *ast.BinaryExpr: - // early return here, since the 2 things can apply - if genMonoUpdateIndexExprT(&pn, n.X) { - n.X = pn - fnUp() - } - if genMonoUpdateIndexExprT(&pn, n.Y) { - n.Y = pn - fnUp() - } - return true - } - return true - } - ast.Inspect(r, fn) -} - -func (x *genMono) trField(f *ast.Field, tpt *ast.Field, hname string, isbytes bool, state genMonoFieldState) (tp *ast.Field) { - var pn *ast.Ident - switch nn := f.Type.(type) { - case *ast.IndexExpr: - if genMonoUpdateIndexExprT(&pn, nn) { - f.Type = pn - } - case *ast.StarExpr: - if genMonoUpdateIndexExprT(&pn, nn.X) { - nn.X = pn - } - case *ast.FuncType: - x.trMethodSignNonRecv(nn.Params, tpt, hname, isbytes) - x.trMethodSignNonRecv(nn.Results, tpt, hname, isbytes) - return - case *ast.ArrayType: - x.trArray(nn, tpt, hname, isbytes) - return - case *ast.Ident: - if state == genMonoFieldRecv || nn.Name != "T" { - return - } - pn = nn // "T" - if state == genMonoFieldParamsResult { - f.Type = &ast.StarExpr{X: pn} - } - } - if pn == nil { - return - } - - tp = x.updateIdentForT(pn, hname, tpt, isbytes, true) - return -} - -func (x *genMono) updateIdentForT(pn *ast.Ident, hname string, tp *ast.Field, - isbytes bool, lookupTP bool) (tp2 *ast.Field) { - sfx, writer, reader, hnameUp := genMonoIsBytesVals(hname, isbytes) - // handle special ones e.g. helperDecReader et al - if slices.Contains(genMonoSpecialFieldTypes, pn.Name) { - pn.Name += sfx - return - } - - if pn.Name != "T" && lookupTP { - tp = x.typParam[pn.Name] - if tp == nil { - tp = x.typParamTransient[pn.Name] - } - } - - paramtyp := tp.Type.(*ast.Ident).Name - if pn.Name == "T" { - switch paramtyp { - case "encDriver", "decDriver": - pn.Name = hname + genMonoTitleCase(paramtyp) + sfx - case "encWriter": - pn.Name = writer - case "decReader": - pn.Name = reader - } - } else { - switch paramtyp { - case "encDriver", "decDriver": - pn.Name += hnameUp + sfx - case "encWriter", "decReader": - pn.Name += sfx - } - } - return tp -} - -func genMonoUpdateIndexExprT(pn **ast.Ident, node ast.Node) (pnok bool) { - *pn = nil - if n2, ok := node.(*ast.IndexExpr); ok { - n9, ok9 := n2.Index.(*ast.Ident) - n3, ok := n2.X.(*ast.Ident) - if ok && ok9 && n9.Name == "T" { - *pn, pnok = ast.NewIdent(n3.Name), true - } - } - return -} - -func genMonoTitleCase(s string) string { - return strings.ToUpper(s[:1]) + s[1:] -} - -func genMonoIsBytesVals(hName string, isbytes bool) (suffix, writer, reader, hNameUp string) { - hNameUp = genMonoTitleCase(hName) - if isbytes { - return "Bytes", "bytesEncAppender", "bytesDecReader", hNameUp - } - return "IO", "bufioEncWriter", "ioDecReader", hNameUp -} - -func genMonoTypeParamsOk(v *ast.FieldList) (ok bool) { - if v == nil || v.List == nil || len(v.List) != 1 { - return false - } - pn := v.List[0] - if len(pn.Names) != 1 { - return false - } - pnName := pn.Names[0].Name - if pnName != "T" { - return false - } - // ignore any nodes which are not idents e.g. cmp.orderedRv - vv, ok := pn.Type.(*ast.Ident) - if !ok { - return false - } - switch vv.Name { - case "encDriver", "decDriver", "encWriter", "decReader": - return true - } - return false -} - -func genMonoCopy(src *ast.File) (dst *ast.File) { - dst = &ast.File{ - Name: &ast.Ident{Name: "codec"}, - } - dst.Decls = append(dst.Decls, src.Decls...) - return -} - -type genMonoStrBuilder struct { - v []byte -} - -func (x *genMonoStrBuilder) s(v string) *genMonoStrBuilder { - x.v = append(x.v, v...) - return x -} - -func genMonoOutInit(importSpecs []*ast.ImportSpec, fname string) (f *ast.File) { - // ParseFile seems to skip the //go:build stanza - // it should be written directly into the file - var s genMonoStrBuilder - s.s(` -package codec - -import ( -`) - for _, v := range importSpecs { - s.s("\t").s(v.Path.Value).s("\n") - } - s.s(")\n") - for _, v := range genMonoRefImportsVia_ { - s.s("var _ = ").s(v[0]).s(".").s(v[1]).s("\n") - } - f, err := parser.ParseFile(token.NewFileSet(), fname, s.v, genMonoParserMode) - halt.onerror(err) - return -} - -func genMonoAll() { - // hdls := []Handle{ - // (*SimpleHandle)(nil), - // (*JsonHandle)(nil), - // (*CborHandle)(nil), - // (*BincHandle)(nil), - // (*MsgpackHandle)(nil), - // } - hdls := []string{"simple", "json", "cbor", "binc", "msgpack"} - var m genMono - m.init() - for _, v := range hdls { - m.hdl(v) - } -} |
