1
0
mirror of https://github.com/Mrs4s/go-cqhttp.git synced 2025-05-05 03:23:49 +08:00
go-cqhttp/db/leveldb/mkrw.go
wdvxdr1123 9054d4cee8
db/leveldb: impl index read/write drop encoding/gob (#1370)
Two benefit below:
 * shrink go-cqhttp binary size about 200KiB
 * shrink database file from 2.8M to 1.56M compared with v2 database

Also provide a tool to migrate v2 database:
https://github.com/RomiChan/gocq-leveldb-migrate
2022-02-15 22:24:27 +08:00

130 lines
3.0 KiB
Go

//go:build ignore
package main
import (
"bytes"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/token"
"os"
)
var output bytes.Buffer
func fprintf(format string, args ...interface{}) {
_, _ = fmt.Fprintf(&output, format, args...)
}
func main() {
f, _ := parser.ParseFile(token.NewFileSet(), "./../database.go", nil, 0)
fprintf("// Code generated by mkrw.go; DO NOT EDIT.\n\n")
fprintf("package leveldb\n\n")
fprintf("import \"github.com/Mrs4s/go-cqhttp/db\"\n\n")
ast.Inspect(f, func(node ast.Node) bool {
switch node := node.(type) {
case *ast.FuncDecl:
return false
case *ast.TypeSpec:
if !node.Name.IsExported() {
return false
}
x, ok := node.Type.(*ast.StructType)
if !ok {
return false
}
if x.Fields != nil && x.Fields.List != nil {
mkWrite(node)
mkRead(node)
}
}
return true
})
out, err := format.Source(output.Bytes())
if err != nil {
fmt.Println(string(output.Bytes()))
panic(err)
}
os.WriteFile("database_gen.go", out, 0o644)
}
func typeName(typ ast.Expr) string {
switch typ := typ.(type) {
case *ast.Ident:
return typ.Name
case *ast.ArrayType:
if typ.Len != nil {
panic("unexpected array type")
}
return "[]" + typeName(typ.Elt)
case *ast.SelectorExpr:
return typeName(typ.X) + "." + typ.Sel.Name
}
panic("unexpected type")
}
func mkWrite(node *ast.TypeSpec) {
typename := node.Name.String()
structType := node.Type.(*ast.StructType)
fprintf("func (w *writer) write%s(x *db.%s) {\n", typename, typename)
fprintf("if x == nil {\n")
fprintf("w.nil()\n")
fprintf("return\n")
fprintf("}\n")
fprintf("w.coder(coderStruct)\n")
for _, field := range structType.Fields.List {
switch typ := field.Type.(type) {
case *ast.Ident:
for _, name := range field.Names {
fprintf("w.%s(x.%s)\n", typ.Name, name.Name)
}
case *ast.ArrayType:
if typeName(typ) != "[]global.MSG" {
panic("unexpected array type")
}
for _, name := range field.Names {
fprintf("w.arrayMsg(x.%s)\n", name.Name)
}
case *ast.StarExpr:
for _, name := range field.Names {
fprintf("w.write%s(x.%s)\n", typeName(typ.X), name.Name)
}
}
}
fprintf("}\n\n")
}
func mkRead(node *ast.TypeSpec) {
typename := node.Name.String()
structType := node.Type.(*ast.StructType)
fprintf(`func (r *reader) read%s() *db.%s {
coder := r.coder()
if coder == coderNil {
return nil
}`+"\n", typename, typename)
fprintf("x := &db.%s{}\n", typename)
for _, field := range structType.Fields.List {
switch typ := field.Type.(type) {
case *ast.Ident:
for _, name := range field.Names {
fprintf("x.%s = r.%s()\n", name.Name, typ.Name)
}
case *ast.ArrayType:
if typeName(typ) != "[]global.MSG" {
panic("unexpected array type")
}
for _, name := range field.Names {
fprintf("x.%s = r.arrayMsg()\n", name.Name)
}
case *ast.StarExpr:
for _, name := range field.Names {
fprintf("x.%s = r.read%s()\n", name.Name, typeName(typ.X))
}
}
}
fprintf("return x\n")
fprintf("}\n\n")
}