github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/internal/generator/c2c_switcher/c2c_switcher.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "go/ast" 6 "go/format" 7 "go/parser" 8 "go/token" 9 "os" 10 "sort" 11 "strconv" 12 "text/template" 13 ) 14 15 const codeTemplate = `// Code generated by internal/generator/c2c_switcher DO NOT EDIT. 16 17 package client 18 19 import ( 20 {{range .Imports}} {{.}} 21 {{end}} 22 ) 23 24 const ( 25 UnknownDecoder = iota 26 {{range .Consts}} {{.}} 27 {{end}} 28 ) 29 30 func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, network.RequestParams), decoderType uint8) { 31 switch msgType { 32 {{range .Decoders}} case {{.Id}}: 33 return {{.Func}}, {{.DecoderType}} 34 {{end}} default: 35 return nil, UnknownDecoder 36 } 37 }` 38 39 type decoder struct { 40 Id int64 41 Func string 42 DecoderType string 43 } 44 type DecoderSort []decoder 45 46 func (d DecoderSort) Len() int { return len(d) } 47 func (d DecoderSort) Swap(i, j int) { d[i], d[j] = d[j], d[i] } 48 func (d DecoderSort) Less(i, j int) bool { return d[i].Id < d[j].Id } 49 50 func main() { 51 type switchFile struct { 52 Imports []string 53 Consts []string 54 Decoders DecoderSort 55 } 56 var sf switchFile 57 58 fset := token.NewFileSet() 59 astF, err := parser.ParseFile(fset, "_c2c_decoders.go", nil, parser.AllErrors|parser.ParseComments) 60 if err != nil { 61 panic(err) 62 } 63 64 sf.Imports = make([]string, 0, len(astF.Imports)) 65 for _, imp := range astF.Imports { 66 sf.Imports = append(sf.Imports, imp.Path.Value) 67 } 68 69 sf.Consts = make([]string, 0, len(astF.Scope.Objects)) 70 for _, obj := range astF.Scope.Objects { 71 if obj.Kind != ast.Var { 72 panic(`unknown non-variable in "_c2c_decoders.go"`) 73 } 74 value := obj.Decl.(*ast.ValueSpec) 75 sf.Consts = append(sf.Consts, obj.Name) 76 for _, value := range value.Values { 77 if value, ok := value.(*ast.CompositeLit); ok { 78 for _, kv := range value.Elts { 79 if kv, ok := kv.(*ast.KeyValueExpr); ok { 80 k := kv.Key.(*ast.BasicLit) 81 v := kv.Value.(*ast.Ident) 82 sf.Decoders = append(sf.Decoders, decoder{ 83 Id: mustParseInt(k.Value), 84 Func: v.Name, 85 DecoderType: obj.Name, 86 }) 87 } else { 88 panic(`unknown key value in ` + obj.Name + ` in "_c2c_decoders.go"`) 89 } 90 } 91 } else { 92 panic(`unknown non-map value in "_c2c_decoders.go"`) 93 } 94 } 95 } 96 sort.Slice(sf.Consts, func(i, j int) bool { 97 return sf.Consts[i] < sf.Consts[j] 98 }) 99 sort.Sort(sf.Decoders) 100 101 f, _ := os.OpenFile("c2c_switch.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0o644) 102 tmpl, err := template.New("template").Parse(codeTemplate) 103 if err != nil { 104 panic(err) 105 } 106 buffer := &bytes.Buffer{} 107 err = tmpl.Execute(buffer, &sf) 108 if err != nil { 109 panic(err) 110 } 111 source, _ := format.Source(buffer.Bytes()) 112 _, _ = f.Write(source) 113 _ = f.Close() 114 } 115 116 func mustParseInt(s string) int64 { 117 i, err := strconv.ParseInt(s, 10, 32) 118 if err != nil { 119 panic(err) 120 } 121 return i 122 }