mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-05-04 11:07:40 +08:00
name old time/op new time/op delta JceWriter_WriteMap-8 2.34µs ± 2% 0.69µs ± 4% -70.63% (p=0.008 n=5+5) JceWriter_WriteJceStructRaw-8 1.28µs ± 1% 0.42µs ± 1% -66.86% (p=0.008 n=5+5) name old speed new speed delta JceWriter_WriteMap-8 39.7MB/s ± 2% 135.4MB/s ± 4% +240.56% (p=0.008 n=5+5) JceWriter_WriteJceStructRaw-8 82.3MB/s ± 1% 219.9MB/s ± 1% +167.32% (p=0.008 n=5+5) name old alloc/op new alloc/op delta JceWriter_WriteMap-8 1.30kB ± 0% 0.21kB ± 0% -84.05% (p=0.008 n=5+5) JceWriter_WriteJceStructRaw-8 640B ± 0% 208B ± 0% -67.50% (p=0.008 n=5+5) name old allocs/op new allocs/op delta JceWriter_WriteMap-8 30.0 ± 0% 2.0 ± 0% -93.33% (p=0.008 n=5+5) JceWriter_WriteJceStructRaw-8 15.0 ± 0% 2.0 ± 0% -86.67% (p=0.008 n=5+5)
157 lines
4.3 KiB
Go
157 lines
4.3 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/Mrs4s/MiraiGo/binary/jce"
|
|
)
|
|
|
|
const head = `// Code generated by structs_parser; DO NOT EDIT.
|
|
|
|
package jce
|
|
|
|
`
|
|
|
|
func main() {
|
|
f := flag.String("f", "structs_tobytes.go", "output file.")
|
|
flag.Parse()
|
|
fmt.Println("gen runs on arg", *f)
|
|
w, err := os.Create(*f)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
w.WriteString(head)
|
|
WriteJceStruct(w, &jce.RequestPacket{})
|
|
WriteJceStruct(w, &jce.RequestDataVersion3{})
|
|
WriteJceStruct(w, &jce.RequestDataVersion2{})
|
|
WriteJceStruct(w, &jce.SvcReqRegister{})
|
|
WriteJceStruct(w, &jce.FriendListRequest{})
|
|
WriteJceStruct(w, &jce.SummaryCardReq{})
|
|
WriteJceStruct(w, &jce.SummaryCardReqSearch{})
|
|
WriteJceStruct(w, &jce.TroopListRequest{})
|
|
WriteJceStruct(w, &jce.TroopMemberListRequest{})
|
|
WriteJceStruct(w, &jce.SvcRespPushMsg{})
|
|
WriteJceStruct(w, &jce.ModifyGroupCardRequest{})
|
|
WriteJceStruct(w, &jce.SvcReqGetDevLoginInfo{})
|
|
WriteJceStruct(w, &jce.SvcReqRegisterNew{})
|
|
WriteJceStruct(w, &jce.DelFriendReq{})
|
|
err = w.Close()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func writeObject(w io.Writer, v reflect.Value, tag byte, name string) {
|
|
k := v.Kind()
|
|
if k == reflect.Map {
|
|
switch v.Interface().(type) {
|
|
case map[string]string:
|
|
w.Write([]byte(fmt.Sprintf("\tw.writeMapStrStr(pkt.%s, %d)\n", name, tag)))
|
|
case map[string][]byte:
|
|
w.Write([]byte(fmt.Sprintf("\tw.writeMapStrBytes(pkt.%s, %d)\n", name, tag)))
|
|
case map[string]map[string][]byte:
|
|
w.Write([]byte(fmt.Sprintf("\tw.writeMapStrMapStrBytes(pkt.%s, %d)\n", name, tag)))
|
|
default:
|
|
w.Write([]byte(fmt.Sprintf("\tw.writeMap(pkt.%s, %d)\n", name, tag)))
|
|
}
|
|
return
|
|
}
|
|
if k == reflect.Slice {
|
|
switch v.Interface().(type) {
|
|
case []byte:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteBytes(pkt.%s, %d)\n", name, tag)))
|
|
case []int64:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteInt64Slice(pkt.%s, %d)\n", name, tag)))
|
|
case [][]byte:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteBytesSlice(pkt.%s, %d)\n", name, tag)))
|
|
case []jce.IJceStruct:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteJceStructSlice(pkt.%s, %d)\n", name, tag)))
|
|
default:
|
|
w.Write([]byte(fmt.Sprintf("\tw.writeSlice(pkt.%s, %d)\n", name, tag)))
|
|
}
|
|
return
|
|
}
|
|
switch k {
|
|
case reflect.Uint8, reflect.Int8:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteByte(byte(pkt.%s), %d)\n", name, tag)))
|
|
case reflect.Uint16, reflect.Int16:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteInt16(int16(pkt.%s), %d)\n", name, tag)))
|
|
case reflect.Uint32, reflect.Int32:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteInt32(int32(pkt.%s), %d)\n", name, tag)))
|
|
case reflect.Uint64, reflect.Int64:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteInt64(int64(pkt.%s), %d)\n", name, tag)))
|
|
case reflect.String:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteString(pkt.%s, %d)\n", name, tag)))
|
|
default:
|
|
switch v.Interface().(type) {
|
|
case jce.IJceStruct:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteJceStruct(pkt.%s, %d)\n", name, tag)))
|
|
case float32:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteFloat32(pkt.%s, %d)\n", name, tag)))
|
|
case float64:
|
|
w.Write([]byte(fmt.Sprintf("\tw.WriteFloat64(pkt.%s, %d)\n", name, tag)))
|
|
}
|
|
}
|
|
}
|
|
|
|
type decoder struct {
|
|
index int
|
|
id int
|
|
name string
|
|
}
|
|
|
|
var decoderCache = sync.Map{}
|
|
|
|
// writeJceStructRaw 写入 Jce 结构体
|
|
func writeJceStructRaw(w io.Writer, s interface{}) {
|
|
t := reflect.TypeOf(s)
|
|
if t.Kind() != reflect.Ptr {
|
|
return
|
|
}
|
|
t = t.Elem()
|
|
v := reflect.ValueOf(s).Elem()
|
|
var jceDec []decoder
|
|
dec, ok := decoderCache.Load(t)
|
|
if ok { // 从缓存中加载
|
|
jceDec = dec.([]decoder)
|
|
} else { // 初次反射
|
|
jceDec = make([]decoder, 0, t.NumField())
|
|
for i := 0; i < t.NumField(); i++ {
|
|
field := t.Field(i)
|
|
strId := field.Tag.Get("jceId")
|
|
if strId == "" {
|
|
continue
|
|
}
|
|
id, err := strconv.Atoi(strId)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
jceDec = append(jceDec, decoder{
|
|
index: i,
|
|
id: id,
|
|
name: field.Name,
|
|
})
|
|
}
|
|
decoderCache.Store(t, jceDec) // 存入缓存
|
|
}
|
|
for _, dec := range jceDec {
|
|
obj := v.Field(dec.index)
|
|
writeObject(w, obj, byte(dec.id), dec.name)
|
|
}
|
|
}
|
|
|
|
func WriteJceStruct(w io.Writer, s jce.IJceStruct) {
|
|
w.Write([]byte(fmt.Sprintf("func (pkt %s) ToBytes() []byte {\n", strings.ReplaceAll(reflect.TypeOf(s).String(), "jce.", ""))))
|
|
w.Write([]byte("\tw := NewJceWriter()\n"))
|
|
writeJceStructRaw(w, s)
|
|
w.Write([]byte("\treturn w.Bytes()\n"))
|
|
w.Write([]byte("}\n\n"))
|
|
}
|