1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 19:17:38 +08:00

binary/jce: use go/parser generator

This commit is contained in:
wdvxdr 2021-12-12 14:37:23 +08:00
parent 45692b75f8
commit 5ff69f3c3a
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
8 changed files with 377 additions and 371 deletions

View File

@ -1,92 +0,0 @@
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"os"
"os/exec"
"strings"
_ "embed"
)
//go:embed structs_parser_tmp.go
var tmpmain string
func main() {
f := flag.String("f", "structs_tobytes.go", "output file.")
i := flag.String("i", "structs.go", "input file.")
flag.Parse()
fmt.Println("gen runs on arg", *f, *i)
fmt.Println("len of tmp main is", len(tmpmain))
tmp, err := os.Create("tmp.go")
if err != nil {
panic(err)
}
inp, err := os.Open(*i)
if err != nil {
panic(err)
}
var structs []string
var isinhead = true
var isinfill = false
var isnexttemplate = false
s := bufio.NewScanner(bytes.NewReader([]byte(tmpmain)))
for s.Scan() {
line := s.Text()
if isinhead {
if strings.Contains(line, "Main_") {
line = "func main() {"
isnexttemplate = true
isinhead = false
scanner := bufio.NewScanner(inp)
start := false
for scanner.Scan() {
t := scanner.Text()
if t == "type (" {
start = true
}
if start {
tmp.WriteString(t + "\n")
if t == ")" {
break
}
if strings.Contains(t, " struct {") {
structs = append(structs, strings.Trim(t[:len(t)-9], "\t"))
}
}
}
inp.Close()
}
tmp.WriteString(line + "\n")
} else if isinfill {
for _, s := range structs {
fmt.Fprintf(tmp, "\tWriteJceStruct(w, &%s{})\n", s)
}
isinfill = false
tmp.WriteString("// structs_parser: fill area\n")
tmp.WriteString(line + "\n")
} else {
if strings.Contains(line, "// structs_parser: fill area") {
isinfill = true
tmp.WriteString("// structs_parser: fill area\n")
} else {
if isnexttemplate {
fmt.Fprintf(tmp, line+"\n", *f)
isnexttemplate = false
} else {
tmp.WriteString(line + "\n")
}
}
}
}
tmp.Close()
c := exec.Command("go", "run", "tmp.go")
err = c.Run()
if err != nil {
panic(err)
}
os.Remove("tmp.go")
}

View File

@ -1,149 +0,0 @@
package main
import (
"fmt"
"io"
"os"
"reflect"
"strconv"
"strings"
"sync"
)
type IJceStruct interface{}
const head = "// Code generated by structs_parser; DO NOT EDIT.\npackage jce\n"
func Main_() {
w, err := os.Create("%s")
if err != nil {
panic(err)
}
w.WriteString(head)
// structs_parser: fill area
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)))
default:
writeJceStructSlice(w, tag, name)
}
return
}
switch k {
case reflect.Uint8, reflect.Int8:
w.Write([]byte(fmt.Sprintf("\tw.WriteByte(pkt.%s, %d)\n", name, tag)))
case reflect.Uint16, reflect.Int16:
w.Write([]byte(fmt.Sprintf("\tw.WriteInt16(pkt.%s, %d)\n", name, tag)))
case reflect.Uint32, reflect.Int32:
w.Write([]byte(fmt.Sprintf("\tw.WriteInt32(pkt.%s, %d)\n", name, tag)))
case reflect.Uint64, reflect.Int64:
w.Write([]byte(fmt.Sprintf("\tw.WriteInt64(pkt.%s, %d)\n", name, tag)))
case reflect.Int, reflect.Uint:
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)))
case reflect.Interface, reflect.Ptr:
w.Write([]byte(fmt.Sprintf("\tw.writeHead(10, %d)\n", tag)))
w.Write([]byte(fmt.Sprintf("\tw.buf.Write(pkt.%s.ToBytes())\n", name)))
w.Write([]byte("\tw.writeHead(11, 0)\n"))
default:
switch v.Interface().(type) {
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 writeJceStructSlice(w io.Writer, tag byte, name string) {
w.Write([]byte(fmt.Sprintf("\tw.writeHead(9, %d)\n", tag)))
w.Write([]byte(fmt.Sprintf("\tif len(pkt.%s) == 0 {\n", name)))
w.Write([]byte("\t\tw.writeHead(12, 0) // w.WriteInt32(0, 0)\n"))
w.Write([]byte("\t} else {\n"))
w.Write([]byte(fmt.Sprintf("\t\tw.WriteInt32(int32(len(pkt.%s)), 0)\n", name)))
w.Write([]byte(fmt.Sprintf("\t\tfor _, i := range pkt.%s {\n", name)))
w.Write([]byte("\t\t\tw.buf.Write(i.ToBytes())\n"))
w.Write([]byte("\t\t}\n"))
w.Write([]byte("\t}\n"))
}
func WriteJceStruct(w io.Writer, s IJceStruct) {
w.Write([]byte(fmt.Sprintf("\nfunc (pkt %s) ToBytes() []byte {\n", strings.ReplaceAll(reflect.TypeOf(s).String(), "main.", ""))))
w.Write([]byte("\tw := NewJceWriter()\n"))
writeJceStructRaw(w, s)
w.Write([]byte("\treturn w.Bytes()\n"))
w.Write([]byte("}\n"))
}

View File

@ -5,7 +5,7 @@ type IJceStruct interface {
ReadFrom(*JceReader) ReadFrom(*JceReader)
} }
//go:generate go run gen/structs_parser.go -f structs_tobytes.go -i structs.go //go:generate go run github.com/Mrs4s/MiraiGo/internal/generator/jce_gen -file=structs.go -o structs_tobytes.go
type ( type (
RequestPacket struct { RequestPacket struct {
IVersion int16 `jceId:"1"` IVersion int16 `jceId:"1"`
@ -75,7 +75,6 @@ type (
} }
SvcReqRegister struct { SvcReqRegister struct {
IJceStruct
Uin int64 `jceId:"0"` Uin int64 `jceId:"0"`
Bid int64 `jceId:"1"` Bid int64 `jceId:"1"`
ConnType byte `jceId:"2"` ConnType byte `jceId:"2"`
@ -140,7 +139,6 @@ type (
} }
SvcReqRegisterNew struct { SvcReqRegisterNew struct {
IJceStruct
RequestOptional int64 `jceId:"0"` RequestOptional int64 `jceId:"0"`
C2CMsg IJceStruct `jceId:"1"` // SvcReqGetMsgV2 C2CMsg IJceStruct `jceId:"1"` // SvcReqGetMsgV2
GroupMsg IJceStruct `jceId:"2"` // SvcReqPullGroupMsgSeq GroupMsg IJceStruct `jceId:"2"` // SvcReqPullGroupMsgSeq
@ -174,7 +172,6 @@ type (
} }
PullGroupSeqParam struct { PullGroupSeqParam struct {
IJceStruct
GroupCode int64 `jceId:"0"` GroupCode int64 `jceId:"0"`
LastSeqId int64 `jceId:"1"` LastSeqId int64 `jceId:"1"`
} }
@ -252,7 +249,6 @@ type (
} }
SvcRespPushMsg struct { SvcRespPushMsg struct {
IJceStruct
Uin int64 `jceId:"0"` Uin int64 `jceId:"0"`
DelInfos []IJceStruct `jceId:"1"` DelInfos []IJceStruct `jceId:"1"`
Svrip int32 `jceId:"2"` Svrip int32 `jceId:"2"`
@ -300,7 +296,6 @@ type (
} }
FriendListRequest struct { FriendListRequest struct {
IJceStruct
Reqtype int32 `jceId:"0"` Reqtype int32 `jceId:"0"`
IfReflush byte `jceId:"1"` IfReflush byte `jceId:"1"`
Uin int64 `jceId:"2"` Uin int64 `jceId:"2"`
@ -382,7 +377,6 @@ type (
} }
TroopListRequest struct { TroopListRequest struct {
IJceStruct
Uin int64 `jceId:"0"` Uin int64 `jceId:"0"`
GetMSFMsgFlag byte `jceId:"1"` GetMSFMsgFlag byte `jceId:"1"`
Cookies []byte `jceId:"2"` Cookies []byte `jceId:"2"`
@ -433,7 +427,6 @@ type (
} }
TroopMemberListRequest struct { TroopMemberListRequest struct {
IJceStruct
Uin int64 `jceId:"0"` Uin int64 `jceId:"0"`
GroupCode int64 `jceId:"1"` GroupCode int64 `jceId:"1"`
NextUin int64 `jceId:"2"` NextUin int64 `jceId:"2"`
@ -483,7 +476,6 @@ type (
} }
ModifyGroupCardRequest struct { ModifyGroupCardRequest struct {
IJceStruct
Zero int64 `jceId:"0"` Zero int64 `jceId:"0"`
GroupCode int64 `jceId:"1"` GroupCode int64 `jceId:"1"`
NewSeq int64 `jceId:"2"` NewSeq int64 `jceId:"2"`
@ -502,7 +494,6 @@ type (
} }
SummaryCardReq struct { SummaryCardReq struct {
IJceStruct
Uin int64 `jceId:"0"` Uin int64 `jceId:"0"`
ComeFrom int32 `jceId:"1"` ComeFrom int32 `jceId:"1"`
QzoneFeedTimestamp int64 `jceId:"2"` QzoneFeedTimestamp int64 `jceId:"2"`
@ -524,7 +515,6 @@ type (
} }
SummaryCardReqSearch struct { SummaryCardReqSearch struct {
IJceStruct
Keyword string `jceId:"0"` Keyword string `jceId:"0"`
CountryCode string `jceId:"1"` CountryCode string `jceId:"1"`
Version int32 `jceId:"2"` Version int32 `jceId:"2"`
@ -532,7 +522,6 @@ type (
} }
DelFriendReq struct { DelFriendReq struct {
IJceStruct
Uin int64 `jceId:"0"` Uin int64 `jceId:"0"`
DelUin int64 `jceId:"1"` DelUin int64 `jceId:"1"`
DelType byte `jceId:"2"` DelType byte `jceId:"2"`

View File

@ -1,4 +1,5 @@
// Code generated by structs_parser; DO NOT EDIT. // Code generated by internal/generator/jce_gen; DO NOT EDIT.
package jce package jce
func (pkt *RequestPacket) ToBytes() []byte { func (pkt *RequestPacket) ToBytes() []byte {
@ -38,70 +39,100 @@ func (pkt *SsoServerInfo) ToBytes() []byte {
func (pkt *FileStoragePushFSSvcList) ToBytes() []byte { func (pkt *FileStoragePushFSSvcList) ToBytes() []byte {
w := NewJceWriter() w := NewJceWriter()
{ // write pkt.UploadList tag=0
w.writeHead(9, 0) w.writeHead(9, 0)
if len(pkt.UploadList) == 0 { if len(pkt.UploadList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.UploadList)), 0) w.WriteInt32(int32(len(pkt.UploadList)), 0)
for _, i := range pkt.UploadList { for _, i := range pkt.UploadList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
} }
} }
}
{ // write pkt.PicDownloadList tag=1
w.writeHead(9, 1) w.writeHead(9, 1)
if len(pkt.PicDownloadList) == 0 { if len(pkt.PicDownloadList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.PicDownloadList)), 0) w.WriteInt32(int32(len(pkt.PicDownloadList)), 0)
for _, i := range pkt.PicDownloadList { for _, i := range pkt.PicDownloadList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
} }
} }
}
{ // write pkt.GPicDownloadList tag=2
w.writeHead(9, 2) w.writeHead(9, 2)
if len(pkt.GPicDownloadList) == 0 { if len(pkt.GPicDownloadList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.GPicDownloadList)), 0) w.WriteInt32(int32(len(pkt.GPicDownloadList)), 0)
for _, i := range pkt.GPicDownloadList { for _, i := range pkt.GPicDownloadList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
} }
} }
}
{ // write pkt.QZoneProxyServiceList tag=3
w.writeHead(9, 3) w.writeHead(9, 3)
if len(pkt.QZoneProxyServiceList) == 0 { if len(pkt.QZoneProxyServiceList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.QZoneProxyServiceList)), 0) w.WriteInt32(int32(len(pkt.QZoneProxyServiceList)), 0)
for _, i := range pkt.QZoneProxyServiceList { for _, i := range pkt.QZoneProxyServiceList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
} }
} }
}
{ // write pkt.UrlEncodeServiceList tag=4
w.writeHead(9, 4) w.writeHead(9, 4)
if len(pkt.UrlEncodeServiceList) == 0 { if len(pkt.UrlEncodeServiceList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.UrlEncodeServiceList)), 0) w.WriteInt32(int32(len(pkt.UrlEncodeServiceList)), 0)
for _, i := range pkt.UrlEncodeServiceList { for _, i := range pkt.UrlEncodeServiceList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
} }
} }
}
{ // write BigDataChannel tag=5
w.writeHead(10, 5) w.writeHead(10, 5)
w.buf.Write(pkt.BigDataChannel.ToBytes()) w.buf.Write(pkt.BigDataChannel.ToBytes())
w.writeHead(11, 0) w.writeHead(11, 0)
}
{ // write pkt.VipEmotionList tag=6
w.writeHead(9, 6) w.writeHead(9, 6)
if len(pkt.VipEmotionList) == 0 { if len(pkt.VipEmotionList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.VipEmotionList)), 0) w.WriteInt32(int32(len(pkt.VipEmotionList)), 0)
for _, i := range pkt.VipEmotionList { for _, i := range pkt.VipEmotionList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
} }
} }
}
{ // write pkt.C2CPicDownList tag=7
w.writeHead(9, 7) w.writeHead(9, 7)
if len(pkt.C2CPicDownList) == 0 { if len(pkt.C2CPicDownList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.C2CPicDownList)), 0) w.WriteInt32(int32(len(pkt.C2CPicDownList)), 0)
for _, i := range pkt.C2CPicDownList { for _, i := range pkt.C2CPicDownList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
} }
} }
w.WriteBytes(pkt.PttList, 10) w.WriteBytes(pkt.PttList, 10)
@ -117,13 +148,17 @@ func (pkt *FileStorageServerInfo) ToBytes() []byte {
func (pkt *BigDataChannel) ToBytes() []byte { func (pkt *BigDataChannel) ToBytes() []byte {
w := NewJceWriter() w := NewJceWriter()
{ // write pkt.IPLists tag=0
w.writeHead(9, 0) w.writeHead(9, 0)
if len(pkt.IPLists) == 0 { if len(pkt.IPLists) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.IPLists)), 0) w.WriteInt32(int32(len(pkt.IPLists)), 0)
for _, i := range pkt.IPLists { for _, i := range pkt.IPLists {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
} }
} }
w.WriteBytes(pkt.SigSession, 1) w.WriteBytes(pkt.SigSession, 1)
@ -137,13 +172,17 @@ func (pkt *BigDataChannel) ToBytes() []byte {
func (pkt *BigDataIPList) ToBytes() []byte { func (pkt *BigDataIPList) ToBytes() []byte {
w := NewJceWriter() w := NewJceWriter()
w.WriteInt64(pkt.ServiceType, 0) w.WriteInt64(pkt.ServiceType, 0)
{ // write pkt.IPList tag=1
w.writeHead(9, 1) w.writeHead(9, 1)
if len(pkt.IPList) == 0 { if len(pkt.IPList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.IPList)), 0) w.WriteInt32(int32(len(pkt.IPList)), 0)
for _, i := range pkt.IPList { for _, i := range pkt.IPList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
} }
} }
w.WriteInt64(pkt.FragmentSize, 3) w.WriteInt64(pkt.FragmentSize, 3)
@ -229,12 +268,16 @@ func (pkt *SvcRespRegister) ToBytes() []byte {
func (pkt *SvcReqRegisterNew) ToBytes() []byte { func (pkt *SvcReqRegisterNew) ToBytes() []byte {
w := NewJceWriter() w := NewJceWriter()
w.WriteInt64(pkt.RequestOptional, 0) w.WriteInt64(pkt.RequestOptional, 0)
{ // write C2CMsg tag=1
w.writeHead(10, 1) w.writeHead(10, 1)
w.buf.Write(pkt.C2CMsg.ToBytes()) w.buf.Write(pkt.C2CMsg.ToBytes())
w.writeHead(11, 0) w.writeHead(11, 0)
}
{ // write GroupMsg tag=2
w.writeHead(10, 2) w.writeHead(10, 2)
w.buf.Write(pkt.GroupMsg.ToBytes()) w.buf.Write(pkt.GroupMsg.ToBytes())
w.writeHead(11, 0) w.writeHead(11, 0)
}
w.WriteByte(pkt.DisGroupMsgFilter, 14) w.WriteByte(pkt.DisGroupMsgFilter, 14)
w.WriteByte(pkt.GroupMask, 15) w.WriteByte(pkt.GroupMask, 15)
w.WriteInt64(pkt.EndSeq, 16) w.WriteInt64(pkt.EndSeq, 16)
@ -261,13 +304,17 @@ func (pkt *SvcReqGetMsgV2) ToBytes() []byte {
func (pkt *SvcReqPullGroupMsgSeq) ToBytes() []byte { func (pkt *SvcReqPullGroupMsgSeq) ToBytes() []byte {
w := NewJceWriter() w := NewJceWriter()
{ // write pkt.GroupInfo tag=0
w.writeHead(9, 0) w.writeHead(9, 0)
if len(pkt.GroupInfo) == 0 { if len(pkt.GroupInfo) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.GroupInfo)), 0) w.WriteInt32(int32(len(pkt.GroupInfo)), 0)
for _, i := range pkt.GroupInfo { for _, i := range pkt.GroupInfo {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
} }
} }
w.WriteByte(pkt.VerifyType, 1) w.WriteByte(pkt.VerifyType, 1)
@ -291,13 +338,17 @@ func (pkt *SvcRespParam) ToBytes() []byte {
w.WriteInt32(pkt.IsSupportViewPCFile, 4) w.WriteInt32(pkt.IsSupportViewPCFile, 4)
w.WriteInt32(pkt.PcVersion, 5) w.WriteInt32(pkt.PcVersion, 5)
w.WriteInt64(pkt.RoamFlag, 6) w.WriteInt64(pkt.RoamFlag, 6)
{ // write pkt.OnlineInfos tag=7
w.writeHead(9, 7) w.writeHead(9, 7)
if len(pkt.OnlineInfos) == 0 { if len(pkt.OnlineInfos) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.OnlineInfos)), 0) w.WriteInt32(int32(len(pkt.OnlineInfos)), 0)
for _, i := range pkt.OnlineInfos { for _, i := range pkt.OnlineInfos {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
} }
} }
w.WriteInt32(pkt.PCClientType, 8) w.WriteInt32(pkt.PCClientType, 8)
@ -339,13 +390,17 @@ func (pkt *SvcReqMSFLoginNotify) ToBytes() []byte {
w.WriteString(pkt.Info, 5) w.WriteString(pkt.Info, 5)
w.WriteInt64(pkt.ProductType, 6) w.WriteInt64(pkt.ProductType, 6)
w.WriteInt64(pkt.ClientType, 7) w.WriteInt64(pkt.ClientType, 7)
{ // write pkt.InstanceList tag=8
w.writeHead(9, 8) w.writeHead(9, 8)
if len(pkt.InstanceList) == 0 { if len(pkt.InstanceList) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.InstanceList)), 0) w.WriteInt32(int32(len(pkt.InstanceList)), 0)
for _, i := range pkt.InstanceList { for _, i := range pkt.InstanceList {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
} }
} }
return w.Bytes() return w.Bytes()
@ -385,13 +440,17 @@ func (pkt *PushMessageInfo) ToBytes() []byte {
func (pkt *SvcRespPushMsg) ToBytes() []byte { func (pkt *SvcRespPushMsg) ToBytes() []byte {
w := NewJceWriter() w := NewJceWriter()
w.WriteInt64(pkt.Uin, 0) w.WriteInt64(pkt.Uin, 0)
{ // write pkt.DelInfos tag=1
w.writeHead(9, 1) w.writeHead(9, 1)
if len(pkt.DelInfos) == 0 { if len(pkt.DelInfos) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.DelInfos)), 0) w.WriteInt32(int32(len(pkt.DelInfos)), 0)
for _, i := range pkt.DelInfos { for _, i := range pkt.DelInfos {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
} }
} }
w.WriteInt32(pkt.Svrip, 2) w.WriteInt32(pkt.Svrip, 2)
@ -412,11 +471,6 @@ func (pkt *SvcReqGetDevLoginInfo) ToBytes() []byte {
return w.Bytes() return w.Bytes()
} }
func (pkt *SvcDevLoginInfo) ToBytes() []byte {
w := NewJceWriter()
return w.Bytes()
}
func (pkt *DelMsgInfo) ToBytes() []byte { func (pkt *DelMsgInfo) ToBytes() []byte {
w := NewJceWriter() w := NewJceWriter()
w.WriteInt64(pkt.FromUin, 0) w.WriteInt64(pkt.FromUin, 0)
@ -630,13 +684,17 @@ func (pkt *ModifyGroupCardRequest) ToBytes() []byte {
w.WriteInt64(pkt.Zero, 0) w.WriteInt64(pkt.Zero, 0)
w.WriteInt64(pkt.GroupCode, 1) w.WriteInt64(pkt.GroupCode, 1)
w.WriteInt64(pkt.NewSeq, 2) w.WriteInt64(pkt.NewSeq, 2)
{ // write pkt.UinInfo tag=3
w.writeHead(9, 3) w.writeHead(9, 3)
if len(pkt.UinInfo) == 0 { if len(pkt.UinInfo) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0) w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else { } else {
w.WriteInt32(int32(len(pkt.UinInfo)), 0) w.WriteInt32(int32(len(pkt.UinInfo)), 0)
for _, i := range pkt.UinInfo { for _, i := range pkt.UinInfo {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes()) w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
} }
} }
return w.Bytes() return w.Bytes()

View File

@ -1,6 +1,6 @@
package client package client
//go:generate go run cmd/c2c_switcher.go //go:generate go run github.com/Mrs4s/MiraiGo/internal/generator/c2c_switcher
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
// Code generated by client/c2c_switcher.go DO NOT EDIT. // Code generated by internal/generator/c2c_switcher DO NOT EDIT.
package client package client
@ -9,10 +9,10 @@ import (
const ( const (
UnknownDecoder = iota UnknownDecoder = iota
nonSvcNotifyTroopSystemMsgDecoders nonSvcNotifyTroopSystemMsgDecoders
troopSystemMsgDecoders
sysMsgDecoders
otherDecoders otherDecoders
privateMsgDecoders privateMsgDecoders
sysMsgDecoders
troopSystemMsgDecoders
) )
func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *incomingPacketInfo), decoderType uint8) { func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *incomingPacketInfo), decoderType uint8) {

View File

@ -12,7 +12,7 @@ import (
"text/template" "text/template"
) )
const codeTemplate = `// Code generated by client/c2c_switcher.go DO NOT EDIT. const codeTemplate = `// Code generated by internal/generator/c2c_switcher DO NOT EDIT.
package client package client
@ -93,6 +93,9 @@ func main() {
} }
} }
} }
sort.Slice(sf.Consts, func(i, j int) bool {
return sf.Consts[i] < sf.Consts[j]
})
sort.Sort(sf.Decoders) sort.Sort(sf.Decoders)
f, _ := os.OpenFile("c2c_switch.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0o644) f, _ := os.OpenFile("c2c_switch.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0o644)

View File

@ -0,0 +1,197 @@
package main
import (
"bytes"
"flag"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/token"
"io"
"os"
"reflect"
"strconv"
)
type JceField struct {
Name string
Type ast.Expr
Id int
}
type JceStruct struct {
Name string
Fields []JceField
}
type Generator struct {
JceStructs []JceStruct
}
func main() {
file := flag.String("file", "structs.txt", "file to parse")
output := flag.String("o", "", "output file")
flag.Parse()
f, err := parser.ParseFile(token.NewFileSet(), *file, nil, parser.ParseComments)
assert(err == nil, err)
g := Generator{}
ast.Inspect(f, func(n ast.Node) bool {
switch n := n.(type) {
case *ast.FuncDecl:
return false
case *ast.TypeSpec:
x, ok := n.Type.(*ast.StructType)
if !ok {
return false
}
if x.Fields != nil {
var jce JceStruct
for _, f := range x.Fields.List {
if f.Tag == nil {
continue
}
unquoted, _ := strconv.Unquote(f.Tag.Value)
tag, ok := reflect.StructTag(unquoted).Lookup("jceId")
if !ok {
continue
}
id, _ := strconv.Atoi(tag)
if len(f.Names) != 1 {
panic("unexpected name count")
}
jce.Fields = append(jce.Fields, JceField{
Name: f.Names[0].Name,
Type: f.Type,
Id: id,
})
}
jce.Name = n.Name.Name
g.JceStructs = append(g.JceStructs, jce)
}
}
return true
})
buf := new(bytes.Buffer)
assert(err == nil, err)
g.Generate(buf)
formated, err := format.Source(buf.Bytes())
if err != nil {
fmt.Printf("%s\n", buf.Bytes())
panic(err)
}
_ = os.WriteFile(*output, formated, 0644)
}
func (g Generator) Generate(w io.Writer) {
io.WriteString(w, "// Code generated by internal/generator/jce_gen; DO NOT EDIT.\n\npackage jce\n\n")
for _, jce := range g.JceStructs {
if jce.Name == "" || len(jce.Fields) == 0 {
continue
}
var generate func(typ ast.Expr, i int)
generate = func(typ ast.Expr, i int) {
field := jce.Fields[i]
switch typ := typ.(type) {
case *ast.Ident:
switch typ.Name {
case "uint8", "uint16", "uint32", "uint64":
typename := []byte(typ.Name)[1:]
casted := fmt.Sprintf("%s(pkt.%s)", typename, field.Name)
typename[0] ^= ' '
fmt.Fprintf(w, "w.Write%s(%s, %d)\n", typename, casted, field.Id)
case "int8", "int16", "int32", "int64",
"byte", "string":
typename := []byte(typ.Name)
typename[0] ^= ' '
fmt.Fprintf(w, "w.Write%s(pkt.%s, %d)\n", typename, field.Name, field.Id)
case "int":
fmt.Fprintf(w, "w.WriteInt64(int64(pkt.%s), %d)\n", field.Name, field.Id)
default:
fmt.Fprintf(w, `{ // write %s tag=%d
w.writeHead(10, %d)
w.buf.Write(pkt.%s.ToBytes())
w.writeHead(11, 0)}`+"\n", field.Name, field.Id, field.Id, field.Name)
}
case *ast.StarExpr:
_ = typ.X.(*ast.Ident) // assert
generate(typ.X, i)
case *ast.ArrayType:
assert(typ.Len == nil, "unexpected array len")
var method string
switch typeName(typ) {
case "[]byte":
method = "WriteBytes"
case "[]int64":
method = "WriteInt64Slice"
case "[][]byte":
method = "WriteBytesSlice"
default:
fmt.Fprintf(w,
"\t"+`{ // write pkt.%s tag=%d
w.writeHead(9, %d)
if len(pkt.%s) == 0 {
w.writeHead(12, 0) // w.WriteInt32(0, 0)
} else {
w.WriteInt32(int32(len(pkt.%s)), 0)
for _, i := range pkt.%s {
w.writeHead(10, 0)
w.buf.Write(i.ToBytes())
w.writeHead(11, 0)
}
}}`+"\n", field.Name, field.Id, field.Id, field.Name, field.Name, field.Name)
return
}
assert(method != "", typeName(typ))
fmt.Fprintf(w, "w.%s(pkt.%s, %d)\n", method, field.Name, field.Id)
case *ast.MapType:
var method string
typName := typeName(typ)
switch typName {
case "map[string]string":
method = "writeMapStrStr"
case "map[string][]byte":
method = "writeMapStrBytes"
case "map[string]map[string][]byte":
method = "writeMapStrMapStrBytes"
}
assert(method != "", typName)
fmt.Fprintf(w, "w.%s(pkt.%s, %d)\n", method, field.Name, field.Id)
}
}
fmt.Fprintf(w, "func (pkt *%s) ToBytes() []byte {\nw := NewJceWriter()\n", jce.Name)
for i := range jce.Fields {
generate(jce.Fields[i].Type, i)
}
fmt.Fprintf(w, "return w.Bytes()\n}\n\n")
}
}
func assert(cond bool, val interface{}) {
if !cond {
panic("assertion failed: " + fmt.Sprint(val))
}
}
func typeName(typ ast.Expr) string {
switch typ := typ.(type) {
case *ast.Ident:
return typ.Name
case *ast.StarExpr:
return "*" + typeName(typ.X)
case *ast.ArrayType:
if typ.Len != nil {
panic("unexpected array type")
}
return "[]" + typeName(typ.Elt)
case *ast.MapType:
return "map[" + typeName(typ.Key) + "]" + typeName(typ.Value)
}
panic("unexpected type")
}