1 Star 0 Fork 0

FlyingOnion/gen-bsa

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
gen-bsa.go 22.27 KB
一键复制 编辑 原始数据 按行查看 历史
FlyingOnion 提交于 2022-05-24 09:35 . remove unnecessary type conversion
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
package main
import (
"go/ast"
"go/token"
"go/types"
"os"
"gitee.com/FlyingOnion/wtflog"
. "gitee.com/FlyingOnion/wtflog/types"
"golang.org/x/tools/go/packages"
)
var (
logger = wtflog.NewTextLogger()
)
type spec struct {
has bool
idents []identSpec
structs []structSpec
maps []mapSpec
arrays []arraySpec
}
type arraySpec struct {
name string
arrayType *ast.ArrayType
}
type identSpec struct {
name string
ident *ast.Ident
}
type structSpec struct {
name string
structType *ast.StructType
}
type mapSpec struct {
keyType string
isValueBasicType bool
name string
mapType *ast.MapType
}
func getPkg(path string) (*packages.Package, error) {
cfg := &packages.Config{
Mode: packages.LoadSyntax,
Dir: path,
Tests: false,
}
pkgs, err := packages.Load(cfg)
if err != nil {
return nil, err
}
if len(pkgs) > 0 {
return pkgs[0], nil
}
return nil, nil
}
func getSpecs(pkg *packages.Package) *spec {
structs := []structSpec{}
maps := []mapSpec{}
idents := []identSpec{}
arrays := []arraySpec{}
has := false
// fmt.Println(pkg.TypesInfo.Types)
for _, f := range pkg.Syntax {
for _, decl := range f.Decls {
if gdecl, ok := decl.(*ast.GenDecl); ok && gdecl.Tok == token.TYPE {
for _, spec := range gdecl.Specs {
if typeSpec, ok2 := spec.(*ast.TypeSpec); ok2 {
if typeSpec.Name.Name == "_" {
continue
}
has = true
switch t := typeSpec.Type.(type) {
case *ast.StructType:
structs = append(structs, structSpec{
name: typeSpec.Name.Name,
structType: t,
})
case *ast.Ident:
if tv, ok := pkg.TypesInfo.Types[t]; ok {
if types.IsInterface(tv.Type) {
logger.Warn(typeSpec.Name.Name, "is an interface, skipped.")
} else {
idents = append(idents, identSpec{
name: typeSpec.Name.Name,
ident: t,
})
}
}
case *ast.ArrayType:
arrays = append(arrays, arraySpec{
name: typeSpec.Name.Name,
arrayType: t,
})
case *ast.MapType:
// 一些自定义的类型,底层是int, string基本类型的,也需要支持
if keyTypeValue, ok := pkg.TypesInfo.Types[t.Key]; ok {
keyType := keyTypeValue.Type.Underlying().String()
switch keyType {
case "string", "byte",
"int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64":
isValueBasicType := false
vt := types.ExprString(t.Value)
switch vt {
case "string", "byte",
"int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64":
isValueBasicType = true
}
maps = append(maps, mapSpec{
keyType: keyType,
isValueBasicType: isValueBasicType,
name: typeSpec.Name.Name,
mapType: t,
})
default:
logger.Warn(typeSpec.Name.Name, "is a map with unsupported key type.")
logger.Warn("Supported key types (underlying): string, byte, and int/uint family.")
}
}
}
}
}
}
}
}
return &spec{
has: has,
structs: structs,
idents: idents,
arrays: arrays,
maps: maps,
}
}
func main() {
paths := os.Args[1:]
if len(paths) == 0 {
paths = []string{"."}
}
b := NewByteSlice(make([]byte, 0, 200))
showBuiltinFieldWarning := true
for _, path := range paths {
pkg, err := getPkg(path)
if err != nil {
logger.Error(err)
os.Exit(1)
}
if pkg == nil {
logger.Info("No packages found in", path)
continue
}
ss := getSpecs(pkg)
if !ss.has {
logger.Info("No custom types in", path)
continue
}
logger.Info("Got",
Int(len(ss.structs)), "type struct(s),",
Int(len(ss.arrays)), "type array(s),",
Int(len(ss.idents)), "type ident(s),",
Int(len(ss.maps)), "type map(s) in",
path,
)
b.Reset()
b.AppendString("// Code generated by gen-bsa; DO NOT EDIT.\n\n").
AppendString("package ").AppendString(pkg.Name).AppendString("\n\n"). // TODO: modify package name
AppendString("import \"fmt\"\n").
AppendString("import \"sort\"\n").
AppendString("import \"unsafe\"\n").
AppendString("import . \"gitee.com/FlyingOnion/wtflog/types\"\n\n"). // TODO: modify import pkg
AppendString("func fmtPrint(vs ...interface{}) string { return fmt.Sprintf(\"%+v\", vs...) }\n\n").
AppendString("func fmtBool(b bool) string { if b { return \"true\" }; return \"false\"}\n\n").
AppendString("func sortKeys(keys interface{}, less func(i, j int) bool) { sort.Slice(keys, less) }\n").
AppendString("var _ unsafe.Pointer\n\n")
// generate AppendTo for custom structures
for _, _struct := range ss.structs {
if len(_struct.structType.Fields.List) == 0 {
b.AppendString("func (").AppendString(_struct.name).AppendString(") AppendTo(b *ByteSlice) { b.AppendString(\"{}\") }\n\n")
continue
}
b.AppendString("func (p ").AppendString(_struct.name).AppendString(") AppendTo(b *ByteSlice) {\n").
AppendString("\tvar any interface{}\n").
AppendString("\t_ = any\n").
AppendString("\tb.AppendString(\"{")
hasLoggedField := false
for _, structField := range _struct.structType.Fields.List {
if len(structField.Names) == 0 {
if hasLoggedField {
// b.AppendString("\tb.AppendByte(' ').AppendString(\"")
b.AppendString("\tb.AppendString(\" ")
} else {
hasLoggedField = true
}
// a 0-name field means a builtin type
if showBuiltinFieldWarning {
logger.Warn("Builtin struct field is not fully supported. The generated codes may have syntax errors, or the log will be different from your expectation. We suggest you set the name of the field explicitly.")
showBuiltinFieldWarning = false
}
if t, ok := structField.Type.(*ast.Ident); ok {
name := "p." + t.Name
b.AppendString(t.Name).AppendString(":\")\n")
switch t.Name {
case "bool":
appendBool(b, name, 1)
case "byte":
appendByte(b, name, 1)
case "string":
appendString(b, name, 1)
case "error":
appendError(b, name, 1)
case "int", "int8", "int16", "int32", "int64":
appendInt(b, name, 1)
case "uint", "uint8", "uint16", "uint32", "uint64":
appendUint(b, name, 1)
default:
appendAny(b, name, 1)
}
continue
}
if t, ok := structField.Type.(*ast.StarExpr); ok {
switch x := t.X.(type) {
case *ast.Ident:
name := "p." + x.Name
b.AppendString(x.Name).AppendString(":\")\n")
b.AppendString("\tif ").AppendString(name).AppendString(" == nil {\n\t\tb.AppendString(\"<nil>\")\n\t} else {\n")
switch x.Name {
case "bool":
appendPointer(b, name, 2)
appendPointerElem(b, appendBool, name, 2)
// b.AppendString("\t\tb.AppendPointer(uintptr(unsafe.Pointer(elem))).\n").
// AppendString("\t\t\tAppendByte('(').AppendString(fmtBool(*elem)).AppendByte(')')\n")
case "byte":
appendPointer(b, name, 2)
appendPointerElem(b, appendByte, name, 2)
// b.AppendString("\t\tb.AppendPointer(uintptr(unsafe.Pointer(elem))).\n").
// AppendString("\t\t\tAppendByte('(').AppendByte(*elem)).AppendByte(')')\n")
case "string":
appendPointer(b, name, 2)
appendPointerElem(b, appendString, name, 2)
case "int", "int8", "int16", "int32", "int64":
appendPointer(b, name, 2)
appendPointerElem(b, appendInt, name, 2)
case "uint", "uint8", "uint16", "uint32", "uint64":
appendPointer(b, name, 2)
appendPointerElem(b, appendUint, name, 2)
default:
appendAny(b, name, 2)
}
b.AppendString("\t}\n")
case *ast.SelectorExpr:
name := "p." + x.Sel.Name
b.AppendString("\tif ").AppendString(name).AppendString(" == nil {\n\t\tb.AppendString(\"<nil>\")\n\t} else {\n")
appendAny(b, name, 2)
b.AppendString("\t}\n")
}
continue
}
continue
}
// for j, fieldName := range structField.Names {
// }
// if structField.Names[0].Name != "_" {
// if i > 0 {
// b.AppendString("\tb.AppendByte(' ').AppendString(\"")
// }
// } else {
// continue
// }
for _, fieldName := range structField.Names {
if fieldName.Name == "_" {
continue
}
if hasLoggedField {
// b.AppendString("\tb.AppendByte(' ').AppendString(\"")
b.AppendString("\tb.AppendString(\" ")
} else {
hasLoggedField = true
}
b.AppendString(fieldName.Name).AppendString(":\")\n") // add field name
name := "p." + fieldName.Name
switch t := structField.Type.(type) {
case *ast.Ident:
switch t.Name {
case "bool":
appendBool(b, name, 1)
case "byte":
appendByte(b, name, 1)
case "rune":
appendRune(b, name, 1)
case "string":
appendString(b, name, 1)
case "error":
appendError(b, name, 1)
case "int", "int8", "int16", "int32", "int64":
appendInt(b, name, 1)
case "uint", "uint8", "uint16", "uint32", "uint64":
appendUint(b, name, 1)
default:
appendAny(b, name, 1)
}
case *ast.ArrayType:
b.AppendString("\tb.AppendByte('[')\n").
AppendString("\tfor i, elem := range p.").AppendString(fieldName.Name).AppendString(" {\n").
AppendString("\t\tif i > 0 { b.AppendByte(' ') }\n")
switch et := t.Elt.(type) {
case *ast.Ident:
switch et.Name {
// case "byte":
// appendUint(b, "elem", 2)
// b.AppendString("\t\tb.AppendUint64(uint64(elem))\n")
case "bool":
appendBool(b, "elem", 2)
// b.AppendString("\t\tb.AppendString(fmtBool(elem))\n")
case "string":
appendString(b, "elem", 2)
// b.AppendString("\t\tb.AppendString(elem)\n")
case "error":
appendError(b, "elem", 2)
// b.AppendString("\t\tb.AppendString(elem.Error())\n")
case "int", "int8", "int16", "int32", "int64":
appendInt(b, "elem", 2)
// b.AppendString("\t\tb.AppendInt64(int64(elem))\n")
case "byte", "uint", "uint8", "uint16", "uint32", "uint64":
appendUint(b, "elem", 2)
// b.AppendString("\t\tb.AppendUint64(uint64(elem))\n")
default:
appendAny(b, "elem", 2)
// b.AppendString("\t\tany = elem\n").
// AppendString("\t\tif bsa, ok := any.(ByteSliceAppender); ok { bsa.AppendTo(b) } else if str, ok := any.(Stringer); ok { b.AppendString(str.String()) } else { b.AppendString(fmtPrint(any)) }\n")
}
b.AppendString("\t}\n\tb.AppendByte(']')\n")
if et.Name == "byte" {
b.AppendString("\tif len(p.").AppendString(fieldName.Name).AppendString(") > 0 { b.AppendByte('(').AppendBytes(p.").AppendString(fieldName.Name).AppendString(").AppendByte(')') }\n")
}
case *ast.StarExpr:
b.AppendString("\t\tif elem == nil { b.AppendString(\"<nil>\"); continue }\n")
switch x := et.X.(type) {
case *ast.Ident:
switch x.Name {
case "bool":
appendPointer(b, "elem", 2)
appendPointerElem(b, appendBool, "elem", 2)
// b.AppendString("\t\tb.AppendPointer(uintptr(unsafe.Pointer(elem))).\n").
// AppendString("\t\t\tAppendByte('(').AppendString(fmtBool(*elem)).AppendByte(')')\n")
case "byte":
appendPointer(b, "elem", 2)
appendPointerElem(b, appendByte, "elem", 2)
// b.AppendString("\t\tb.AppendPointer(uintptr(unsafe.Pointer(elem))).\n").
// AppendString("\t\t\tAppendByte('(').AppendByte(*elem)).AppendByte(')')\n")
case "string":
appendPointer(b, "elem", 2)
appendPointerElem(b, appendString, "elem", 2)
case "int", "int8", "int16", "int32", "int64":
appendPointer(b, "elem", 2)
appendPointerElem(b, appendInt, "elem", 2)
case "uint", "uint8", "uint16", "uint32", "uint64":
appendPointer(b, "elem", 2)
appendPointerElem(b, appendUint, "elem", 2)
// switch x.Name {
// case "bool", "byte", "string",
// "int", "int8", "int16", "int32", "int64",
// "uint", "uint8", "uint16", "uint32", "uint64":
// // TODO: modify each type pointer
// // b.AppendString("\tfor i, elem := range p.").AppendString(fieldName.Name).AppendString(" {\n").
// // AppendString("\t\tif i > 0 { b.AppendString(\" \") }\n").
// // b.AppendString("\t\tif elem == nil { b.AppendString(\"<nil>\"); continue }\n").
// b.AppendString("\t\tb.AppendPointer(uintptr(unsafe.Pointer(elem))).AppendByte('(')\n")
// // AppendString("\t}\n")
// // AppendString("\tb.AppendByte(']')\n")
default:
// b.AppendString("\tfor i, elem := range p.").AppendString(fieldName.Name).AppendString(" {\n").
// AppendString("\t\tif i > 0 { b.AppendString(\" \") }\n").
// b.AppendString("\t\tany = elem\n").
// AppendString("\t\tif bsa, ok := any.(ByteSliceAppender); ok { bsa.AppendTo(b) } else if str, ok := any.(Stringer); ok { b.AppendString(str.String()) } else { b.AppendString(fmtPrint(any)) }\n").
appendAny(b, "elem", 2)
// b.AppendString("\t}\n")
// AppendString("\tb.AppendByte(']')\n")
}
default:
appendAny(b, "elem", 2)
// b.AppendString("\tfor i, elem := range p.").AppendString(fieldName.Name).AppendString(" {\n").
// AppendString("\t\tif i > 0 { b.AppendString(\" \") }\n").
// AppendString("\t\tany = elem\n").
// AppendString("\t\tif bsa, ok := any.(ByteSliceAppender); ok { bsa.AppendTo(b) } else if str, ok := any.(Stringer); ok { b.AppendString(str.String()) } else { b.AppendString(fmtPrint(any)) }\n").
// AppendString("\t}\n")
}
b.AppendString("\t}\n\tb.AppendByte(']')\n")
default:
appendAny(b, "elem", 2)
b.AppendString("\t}\n\tb.AppendByte(']')\n")
}
// b.AppendString("\t}\n")
case *ast.SelectorExpr:
appendAny(b, name, 1)
case *ast.StarExpr:
switch x := t.X.(type) {
case *ast.Ident:
b.AppendString("\tif ").AppendString(name).AppendString(" == nil {\n\t\tb.AppendString(\"<nil>\")\n\t} else {\n")
switch x.Name {
case "bool":
appendPointer(b, name, 2)
appendPointerElem(b, appendBool, name, 2)
// b.AppendString("\t\tb.AppendPointer(uintptr(unsafe.Pointer(elem))).\n").
// AppendString("\t\t\tAppendByte('(').AppendString(fmtBool(*elem)).AppendByte(')')\n")
case "byte":
appendPointer(b, name, 2)
appendPointerElem(b, appendByte, name, 2)
// b.AppendString("\t\tb.AppendPointer(uintptr(unsafe.Pointer(elem))).\n").
// AppendString("\t\t\tAppendByte('(').AppendByte(*elem)).AppendByte(')')\n")
case "string":
appendPointer(b, name, 2)
appendPointerElem(b, appendString, name, 2)
case "int", "int8", "int16", "int32", "int64":
appendPointer(b, name, 2)
appendPointerElem(b, appendInt, name, 2)
case "uint", "uint8", "uint16", "uint32", "uint64":
appendPointer(b, name, 2)
appendPointerElem(b, appendUint, name, 2)
default:
appendAny(b, name, 2)
}
b.AppendString("\t}\n")
case *ast.SelectorExpr:
b.AppendString("\tif ").AppendString(name).AppendString(" == nil {\n\t\tb.AppendString(\"<nil>\")\n\t} else {\n")
appendAny(b, name, 2)
b.AppendString("\t}\n")
}
case *ast.FuncType, *ast.ChanType:
appendPointer(b, "&p."+fieldName.Name, 1)
}
}
}
if !hasLoggedField {
b.AppendString("}\")\n}\n\n")
continue
}
b.AppendString("\tb.AppendByte('}')\n}\n\n")
}
// generate AppendTo for custom idents
for _, _ident := range ss.idents {
b.AppendString("func (p ").AppendString(_ident.name).AppendString(") AppendTo(b *ByteSlice) {\n")
switch _ident.ident.Name {
case "bool":
appendBool(b, "bool(p)", 1)
// error cannot be initialized
// case "error":
// appendError(b, "error(p)", 1)
case "string":
appendString(b, "string(p)", 1)
case "rune", "int", "int8", "int16", "int32", "int64":
appendInt(b, "p", 1)
case "byte", "uint", "uint8", "uint16", "uint32", "uint64":
appendUint(b, "p", 1)
default:
b.AppendString("\tvar any interface{}\n").
AppendString("\t_ = any\n")
appendAny(b, _ident.ident.Name+"(p)", 1)
}
b.AppendString("}\n\n")
}
for _, _array := range ss.arrays {
b.AppendString("func (p ").AppendString(_array.name).AppendString(") AppendTo(b *ByteSlice) {\n").
AppendString("\tif p == nil { b.AppendString(\"<nil>\"); return }\n").
AppendString("\tvar any interface{}\n").
AppendString("\t_ = any\n").
AppendString("\tb.AppendByte('[')\n").
AppendString("\tfor i, elem := range p {\n").
AppendString("\t\tif i > 0 { b.AppendByte(' ') }\n")
switch et := _array.arrayType.Elt.(type) {
case *ast.Ident:
switch et.Name {
case "bool":
appendBool(b, "elem", 2)
case "string":
appendString(b, "elem", 2)
case "error":
appendError(b, "elem", 2)
case "int", "int8", "int16", "int32", "int64":
appendInt(b, "elem", 2)
case "byte", "uint", "uint8", "uint16", "uint32", "uint64":
appendUint(b, "elem", 2)
default:
appendAny(b, "elem", 2)
}
default:
appendAny(b, "elem", 2)
}
b.AppendString("\t}\n").
AppendString("\tb.AppendByte(']')\n").
AppendString("}\n\n")
}
for _, _map := range ss.maps {
vType := "interface{}"
if _map.isValueBasicType {
vType = types.ExprString(_map.mapType.Value)
}
kvStruct := NewByteSlice(make([]byte, 0, 80))
kvStruct.AppendString("struct{k ").AppendString(_map.keyType).AppendString("; v ").AppendString(vType).AppendByte('}')
b.AppendString("func (p ").AppendString(_map.name).AppendString(") AppendTo(b *ByteSlice) {\n").
AppendString("\tif p == nil { b.AppendString(\"<nil>\"); return }\n").
AppendString("\tif len(p) == 0 { b.AppendString(\"{}\"); return }\n").
AppendString("\tvar any interface{}\n").
AppendString("\t_ = any\n").
AppendString("\tb.AppendByte('{')\n").
AppendString("\tkvs := make([]").Append(kvStruct).AppendString(", 0, len(p))\n").
AppendString("\tfor k, v := range p { kvs = append(kvs, ").Append(kvStruct).AppendString("{k: ").AppendString(_map.keyType).AppendString("(k), v: ").AppendString(vType).AppendString("(v)}) }\n").
AppendString("\tsortKeys(kvs, func(i, j int) bool { return kvs[i].k < kvs[j].k })\n").
AppendString("\tfor i, kv := range kvs {\n").
AppendString("\t\tif i > 0 { b.AppendByte(' ') }\n")
switch _map.keyType {
case "byte":
appendByte(b, "kv.k", 2)
case "string":
appendString(b, "kv.k", 2)
case "int", "int8", "int16", "int32", "int64":
appendInt(b, "kv.k", 2)
case "uint", "uint8", "uint16", "uint32", "uint64":
appendUint(b, "kv.k", 2)
default:
b.AppendString("\t\tb.AppendString(fmtPrint(kv.k))\n")
}
b.AppendString("\t\tb.AppendByte(':')\n")
switch vType {
case "bool":
appendBool(b, "kv.v", 2)
case "byte":
appendByte(b, "kv.v", 2)
case "string":
appendString(b, "kv.v", 2)
case "error":
appendError(b, "kv.v", 2)
case "int", "int8", "int16", "int32", "int64":
appendInt(b, "kv.v", 2)
case "uint", "uint8", "uint16", "uint32", "uint64":
appendUint(b, "kv.v", 2)
case "interface{}":
fallthrough
default:
appendAny(b, "kv.v", 2)
}
b.AppendString("\t}\n").
AppendString("\tb.AppendByte('}')\n").
AppendString("}\n\n")
}
filepath := path + "/wtf__.go"
logger.Info("Write to file", filepath)
f, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
logger.Error(err)
panic(err)
}
f.Write(b.Bytes())
f.Close()
}
logger.Info("Done.")
}
const indent = "\t" // a tab
// type typeAppender struct {
// basic, pointer func(b *ByteSlice, name string, level int)
// }
func appendByte(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendByte(").AppendString(name).AppendString(")\n")
}
func appendRune(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendRune(").AppendString(name).AppendString(")\n")
}
func appendInt(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendInt64(int64(").AppendString(name).AppendString("))\n")
}
func appendUint(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendUint64(uint64(").AppendString(name).AppendString("))\n")
}
func appendBool(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendString(fmtBool(").AppendString(name).AppendString("))\n")
}
func appendString(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendString(").AppendString(name).AppendString(")\n")
}
func appendAny(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("any = ").AppendString(name).AppendByte('\n')
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("if bsa, ok := any.(ByteSliceAppender); ok { bsa.AppendTo(b) } else if str, ok := any.(Stringer); ok { b.AppendString(str.String()) } else { b.AppendString(fmtPrint(any)) }\n")
}
func appendError(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("if ").AppendString(name).AppendString(" == nil { b.AppendString(\"<nil>\") } else { b.AppendString(\"error(\").AppendString(").AppendString(name).AppendString(".Error()).AppendString(\")\") }\n")
}
func appendPointer(b *ByteSlice, name string, level int) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendPointer(uintptr(unsafe.Pointer(").AppendString(name).AppendString(")))\n")
}
func appendPointerElem(b *ByteSlice,
appendElem func(*ByteSlice, string, int),
ptrName string,
level int,
) {
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendByte('(')\n")
appendElem(b, "*"+ptrName, level)
for i := 0; i < level; i++ {
b.AppendString(indent)
}
b.AppendString("b.AppendByte(')')\n")
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/FlyingOnion/gen-bsa.git
git@gitee.com:FlyingOnion/gen-bsa.git
FlyingOnion
gen-bsa
gen-bsa
master

搜索帮助