diff --git a/binary/jce/gen/structs_parser.go b/binary/jce/gen/structs_parser.go index 3b2d30c5..9d941bd6 100644 --- a/binary/jce/gen/structs_parser.go +++ b/binary/jce/gen/structs_parser.go @@ -2,160 +2,25 @@ package main import ( "bufio" + "bytes" "flag" "fmt" "os" "os/exec" "strings" + + _ "embed" ) -const tmphead = `package main - -import ( - "flag" - "fmt" - "io" - "os" - "reflect" - "strconv" - "strings" - "sync" -) - -type IJceStruct interface {} - -const head = "// Code generated by structs_parser; DO NOT EDIT.\npackage jce\n" -` - -const tmpmain = `func main() { - w, err := os.Create(%s) - if err != nil { - panic(err) - } - tmp.WriteString(head) - w.WriteString(head) -` -const tmptail = ` - 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 []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(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.String: - w.Write([]byte(fmt.Sprintf("\tw.WriteString(pkt.%s, %d)\n", name, tag))) - default: - switch v.Interface().(type) { - case 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 IJceStruct) { - w.Write([]byte(fmt.Sprintf("\nfunc (pkt %s) ToBytes() []byte {\n", strings.ReplaceAll(reflect.TypeOf(s).String(), "", "")))) - w.Write([]byte("\tw := NewJceWriter()\n")) - writeJceStructRaw(w, s) - w.Write([]byte("\treturn w.Bytes()\n")) - w.Write([]byte("}\n")) -} - -` +//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) @@ -165,34 +30,63 @@ func main() { panic(err) } var structs []string - tmp.WriteString(tmphead) - scanner := bufio.NewScanner(inp) - start := false - for scanner.Scan() { - if scanner.Text() == "type (" { - start = true - tmp.WriteString("type (\n") - } - if start { - t := scanner.Text() - tmp.WriteString(t + "\n") - if t == ")" { - break + 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() } - if strings.Contains(t, " struct {") { - structs = append(structs, strings.Trim(t[:len(t)-9], "\t")) + 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") + } } } } - inp.Close() - fmt.Fprintf(tmp, tmpmain, *i) - for _, s := range structs { - fmt.Fprintf(tmp, "\tWriteJceStruct(w, &%s{})\n", s) - } - tmp.WriteString(tmptail) tmp.Close() - exec.Command("go", "tmp.go", "-o tmp") - exec.Command("./tmp") + c := exec.Command("go", "run", "tmp.go") + err = c.Run() + if err != nil { + panic(err) + } os.Remove("tmp.go") - os.Remove("tmp") } diff --git a/binary/jce/gen/structs_parser_tmp.go b/binary/jce/gen/structs_parser_tmp.go new file mode 100644 index 00000000..26ccd631 --- /dev/null +++ b/binary/jce/gen/structs_parser_tmp.go @@ -0,0 +1,149 @@ +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))) + 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))) + case IJceStruct: + 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")) + } + } +} + +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")) +} diff --git a/binary/jce/reader_test.go b/binary/jce/reader_test.go index 4bd4c7ea..883897fd 100644 --- a/binary/jce/reader_test.go +++ b/binary/jce/reader_test.go @@ -3,7 +3,10 @@ package jce import ( "math/rand" "reflect" + "strconv" + "sync" "testing" + "unsafe" "github.com/stretchr/testify/assert" ) @@ -130,3 +133,174 @@ func (w *JceWriter) WriteObject(i interface{}, tag byte) { w.WriteJceStruct(o, tag) } } + +func (w *JceWriter) writeObject(v reflect.Value, tag byte) { + k := v.Kind() + if k == reflect.Map { + switch o := v.Interface().(type) { + case map[string]string: + w.writeMapStrStr(o, tag) + case map[string][]byte: + w.writeMapStrBytes(o, tag) + case map[string]map[string][]byte: + w.writeMapStrMapStrBytes(o, tag) + default: + w.writeMap(v, tag) + } + return + } + if k == reflect.Slice { + switch o := v.Interface().(type) { + case []byte: + w.WriteBytes(o, tag) + case []IJceStruct: + w.WriteJceStructSlice(o, tag) + default: + w.writeSlice(v, tag) + } + return + } + switch k { + case reflect.Uint8, reflect.Int8: + w.WriteByte(*(*byte)(pointerOf(v)), tag) + case reflect.Uint16, reflect.Int16: + w.WriteInt16(*(*int16)(pointerOf(v)), tag) + case reflect.Uint32, reflect.Int32: + w.WriteInt32(*(*int32)(pointerOf(v)), tag) + case reflect.Uint64, reflect.Int64: + w.WriteInt64(*(*int64)(pointerOf(v)), tag) + case reflect.String: + w.WriteString(v.String(), tag) + default: + switch o := v.Interface().(type) { + case IJceStruct: + w.WriteJceStruct(o, tag) + case float32: + w.WriteFloat32(o, tag) + case float64: + w.WriteFloat64(o, tag) + } + } +} + +type decoder struct { + index int + id int +} + +var decoderCache = sync.Map{} + +// WriteJceStructRaw 写入 Jce 结构体 +func (w *JceWriter) WriteJceStructRaw(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, + }) + } + decoderCache.Store(t, jceDec) // 存入缓存 + } + for _, dec := range jceDec { + obj := v.Field(dec.index) + w.writeObject(obj, byte(dec.id)) + } +} + +func (w *JceWriter) WriteJceStruct(s IJceStruct, tag byte) { + w.writeHead(10, tag) + w.WriteJceStructRaw(s) + w.writeHead(11, 0) +} + +func (w *JceWriter) WriteSlice(i interface{}, tag byte) { + va := reflect.ValueOf(i) + if va.Kind() != reflect.Slice { + panic("JceWriter.WriteSlice: not a slice") + } + w.writeSlice(va, tag) +} + +func (w *JceWriter) writeSlice(slice reflect.Value, tag byte) { + if slice.Kind() != reflect.Slice { + return + } + w.writeHead(9, tag) + if slice.Len() == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + return + } + w.WriteInt32(int32(slice.Len()), 0) + for i := 0; i < slice.Len(); i++ { + v := slice.Index(i) + w.writeObject(v, 0) + } +} + +func (w *JceWriter) WriteJceStructSlice(l []IJceStruct, tag byte) { + w.writeHead(9, tag) + if len(l) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + return + } + w.WriteInt32(int32(len(l)), 0) + for _, v := range l { + w.WriteJceStruct(v, 0) + } +} + +func (w *JceWriter) WriteMap(m interface{}, tag byte) { + va := reflect.ValueOf(m) + if va.Kind() != reflect.Map { + panic("JceWriter.WriteMap: not a map") + } + w.writeMap(va, tag) +} + +func (w *JceWriter) writeMap(m reflect.Value, tag byte) { + if m.IsNil() { + w.writeHead(8, tag) + w.writeHead(12, 0) // w.WriteInt32(0, 0) + return + } + if m.Kind() != reflect.Map { + return + } + w.writeHead(8, tag) + w.WriteInt32(int32(m.Len()), 0) + iter := m.MapRange() + for iter.Next() { + w.writeObject(iter.Key(), 0) + w.writeObject(iter.Value(), 1) + } +} + +type value struct { + typ unsafe.Pointer + data unsafe.Pointer + flag uintptr +} + +func pointerOf(v reflect.Value) unsafe.Pointer { + return (*value)(unsafe.Pointer(&v)).data +} diff --git a/binary/jce/reflectx.go b/binary/jce/reflectx.go deleted file mode 100644 index 3adf69f4..00000000 --- a/binary/jce/reflectx.go +++ /dev/null @@ -1,16 +0,0 @@ -package jce - -import ( - "reflect" - "unsafe" -) - -type value struct { - typ unsafe.Pointer - data unsafe.Pointer - flag uintptr -} - -func pointerOf(v reflect.Value) unsafe.Pointer { - return (*value)(unsafe.Pointer(&v)).data -} diff --git a/binary/jce/structs.go b/binary/jce/structs.go index ef638eb0..f30e9a63 100644 --- a/binary/jce/structs.go +++ b/binary/jce/structs.go @@ -1,7 +1,7 @@ package jce type IJceStruct interface { - // ToBytes() []byte + ToBytes() []byte ReadFrom(*JceReader) } diff --git a/binary/jce/structs_tobytes.go b/binary/jce/structs_tobytes.go index a7ebea6b..1e042498 100644 --- a/binary/jce/structs_tobytes.go +++ b/binary/jce/structs_tobytes.go @@ -1,8 +1,6 @@ // Code generated by structs_parser; DO NOT EDIT. - package jce - func (pkt *RequestPacket) ToBytes() []byte { w := NewJceWriter() w.WriteInt16(pkt.IVersion, 1) @@ -30,6 +28,136 @@ func (pkt *RequestDataVersion2) ToBytes() []byte { return w.Bytes() } +func (pkt *SsoServerInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteString(pkt.Server, 1) + w.WriteInt32(pkt.Port, 2) + w.WriteString(pkt.Location, 8) + return w.Bytes() +} + +func (pkt *FileStoragePushFSSvcList) ToBytes() []byte { + w := NewJceWriter() + w.writeHead(9, 0) + if len(pkt.UploadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UploadList)), 0) + for _, i := range pkt.UploadList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 1) + if len(pkt.PicDownloadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.PicDownloadList)), 0) + for _, i := range pkt.PicDownloadList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 2) + if len(pkt.GPicDownloadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.GPicDownloadList)), 0) + for _, i := range pkt.GPicDownloadList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 3) + if len(pkt.QZoneProxyServiceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.QZoneProxyServiceList)), 0) + for _, i := range pkt.QZoneProxyServiceList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 4) + if len(pkt.UrlEncodeServiceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UrlEncodeServiceList)), 0) + for _, i := range pkt.UrlEncodeServiceList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(10, 5) + w.buf.Write(pkt.BigDataChannel.ToBytes()) + w.writeHead(11, 0) + w.writeHead(9, 6) + if len(pkt.VipEmotionList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.VipEmotionList)), 0) + for _, i := range pkt.VipEmotionList { + w.buf.Write(i.ToBytes()) + } + } + w.writeHead(9, 7) + if len(pkt.C2CPicDownList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.C2CPicDownList)), 0) + for _, i := range pkt.C2CPicDownList { + w.buf.Write(i.ToBytes()) + } + } + w.WriteBytes(pkt.PttList, 10) + return w.Bytes() +} + +func (pkt *FileStorageServerInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteString(pkt.Server, 1) + w.WriteInt32(pkt.Port, 2) + return w.Bytes() +} + +func (pkt *BigDataChannel) ToBytes() []byte { + w := NewJceWriter() + w.writeHead(9, 0) + if len(pkt.IPLists) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.IPLists)), 0) + for _, i := range pkt.IPLists { + w.buf.Write(i.ToBytes()) + } + } + w.WriteBytes(pkt.SigSession, 1) + w.WriteBytes(pkt.KeySession, 2) + w.WriteInt64(pkt.SigUin, 3) + w.WriteInt32(pkt.ConnectFlag, 4) + w.WriteBytes(pkt.PbBuf, 5) + return w.Bytes() +} + +func (pkt *BigDataIPList) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.ServiceType, 0) + w.writeHead(9, 1) + if len(pkt.IPList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.IPList)), 0) + for _, i := range pkt.IPList { + w.buf.Write(i.ToBytes()) + } + } + w.WriteInt64(pkt.FragmentSize, 3) + return w.Bytes() +} + +func (pkt *BigDataIPInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Type, 0) + w.WriteString(pkt.Server, 1) + w.WriteInt64(pkt.Port, 2) + return w.Bytes() +} + func (pkt *SvcReqRegister) ToBytes() []byte { w := NewJceWriter() w.WriteInt64(pkt.Uin, 0) @@ -73,6 +201,232 @@ func (pkt *SvcReqRegister) ToBytes() []byte { return w.Bytes() } +func (pkt *SvcRespRegister) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt64(pkt.Bid, 1) + w.WriteByte(pkt.ReplyCode, 2) + w.WriteString(pkt.Result, 3) + w.WriteInt64(pkt.ServerTime, 4) + w.WriteByte(pkt.LogQQ, 5) + w.WriteByte(pkt.NeedKik, 6) + w.WriteByte(pkt.UpdateFlag, 7) + w.WriteInt64(pkt.Timestamp, 8) + w.WriteByte(pkt.CrashFlag, 9) + w.WriteString(pkt.ClientIp, 10) + w.WriteInt32(pkt.ClientPort, 11) + w.WriteInt32(pkt.HelloInterval, 12) + w.WriteInt32(pkt.LargeSeq, 13) + w.WriteByte(pkt.LargeSeqUpdate, 14) + w.WriteBytes(pkt.D769RspBody, 15) + w.WriteInt32(pkt.Status, 16) + w.WriteInt64(pkt.ExtOnlineStatus, 17) + w.WriteInt64(pkt.ClientBatteryGetInterval, 18) + w.WriteInt64(pkt.ClientAutoStatusInterval, 19) + return w.Bytes() +} + +func (pkt *SvcReqRegisterNew) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.RequestOptional, 0) + w.WriteByte(pkt.DisGroupMsgFilter, 14) + w.WriteByte(pkt.GroupMask, 15) + w.WriteInt64(pkt.EndSeq, 16) + w.WriteBytes(pkt.O769Body, 20) + return w.Bytes() +} + +func (pkt *SvcReqGetMsgV2) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt32(pkt.DateTime, 1) + w.WriteByte(pkt.RecivePic, 4) + w.WriteInt16(pkt.Ability, 6) + w.WriteByte(pkt.Channel, 9) + w.WriteByte(pkt.Inst, 16) + w.WriteByte(pkt.ChannelEx, 17) + w.WriteBytes(pkt.SyncCookie, 18) + w.WriteInt64(int64(pkt.SyncFlag), 19) + w.WriteByte(pkt.RambleFlag, 20) + w.WriteInt64(pkt.GeneralAbi, 26) + w.WriteBytes(pkt.PubAccountCookie, 27) + return w.Bytes() +} + +func (pkt *SvcReqPullGroupMsgSeq) ToBytes() []byte { + w := NewJceWriter() + w.writeHead(9, 0) + if len(pkt.GroupInfo) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.GroupInfo)), 0) + for _, i := range pkt.GroupInfo { + w.buf.Write(i.ToBytes()) + } + } + w.WriteByte(pkt.VerifyType, 1) + w.WriteInt32(pkt.Filter, 2) + return w.Bytes() +} + +func (pkt *PullGroupSeqParam) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.GroupCode, 0) + w.WriteInt64(pkt.LastSeqId, 1) + return w.Bytes() +} + +func (pkt *SvcRespParam) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt32(pkt.PCStat, 0) + w.WriteInt32(pkt.IsSupportC2CRoamMsg, 1) + w.WriteInt32(pkt.IsSupportDataLine, 2) + w.WriteInt32(pkt.IsSupportPrintable, 3) + w.WriteInt32(pkt.IsSupportViewPCFile, 4) + w.WriteInt32(pkt.PcVersion, 5) + w.WriteInt64(pkt.RoamFlag, 6) + w.writeHead(9, 7) + if len(pkt.OnlineInfos) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.OnlineInfos)), 0) + for _, i := range pkt.OnlineInfos { + w.buf.Write(i.ToBytes()) + } + } + w.WriteInt32(pkt.PCClientType, 8) + return w.Bytes() +} + +func (pkt *RequestPushNotify) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteByte(pkt.Type, 1) + w.WriteString(pkt.Service, 2) + w.WriteString(pkt.Cmd, 3) + w.WriteBytes(pkt.NotifyCookie, 4) + w.WriteInt32(pkt.MsgType, 5) + w.WriteInt32(pkt.UserActive, 6) + w.WriteInt32(pkt.GeneralFlag, 7) + w.WriteInt64(pkt.BindedUin, 8) + return w.Bytes() +} + +func (pkt *OnlineInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt32(pkt.InstanceId, 0) + w.WriteInt32(pkt.ClientType, 1) + w.WriteInt32(pkt.OnlineStatus, 2) + w.WriteInt32(pkt.PlatformId, 3) + w.WriteString(pkt.SubPlatform, 4) + w.WriteInt64(pkt.UClientType, 5) + return w.Bytes() +} + +func (pkt *SvcReqMSFLoginNotify) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.AppId, 0) + w.WriteByte(pkt.Status, 1) + w.WriteByte(pkt.Tablet, 2) + w.WriteInt64(pkt.Platform, 3) + w.WriteString(pkt.Title, 4) + w.WriteString(pkt.Info, 5) + w.WriteInt64(pkt.ProductType, 6) + w.WriteInt64(pkt.ClientType, 7) + w.writeHead(9, 8) + if len(pkt.InstanceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.InstanceList)), 0) + for _, i := range pkt.InstanceList { + w.buf.Write(i.ToBytes()) + } + } + return w.Bytes() +} + +func (pkt *InstanceInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt32(pkt.AppId, 0) + w.WriteByte(pkt.Tablet, 1) + w.WriteInt64(pkt.Platform, 2) + w.WriteInt64(pkt.ProductType, 3) + w.WriteInt64(pkt.ClientType, 4) + return w.Bytes() +} + +func (pkt *PushMessageInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.FromUin, 0) + w.WriteInt64(pkt.MsgTime, 1) + w.WriteInt16(pkt.MsgType, 2) + w.WriteInt16(pkt.MsgSeq, 3) + w.WriteString(pkt.Msg, 4) + w.WriteInt32(pkt.RealMsgTime, 5) + w.WriteBytes(pkt.VMsg, 6) + w.WriteInt64(pkt.AppShareID, 7) + w.WriteBytes(pkt.MsgCookies, 8) + w.WriteBytes(pkt.AppShareCookie, 9) + w.WriteInt64(pkt.MsgUid, 10) + w.WriteInt64(pkt.LastChangeTime, 11) + w.WriteInt64(pkt.FromInstId, 14) + w.WriteBytes(pkt.RemarkOfSender, 15) + w.WriteString(pkt.FromMobile, 16) + w.WriteString(pkt.FromName, 17) + return w.Bytes() +} + +func (pkt *SvcRespPushMsg) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.writeHead(9, 1) + if len(pkt.DelInfos) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.DelInfos)), 0) + for _, i := range pkt.DelInfos { + w.buf.Write(i.ToBytes()) + } + } + w.WriteInt32(pkt.Svrip, 2) + w.WriteBytes(pkt.PushToken, 3) + w.WriteInt32(pkt.ServiceType, 4) + return w.Bytes() +} + +func (pkt *SvcReqGetDevLoginInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteBytes(pkt.Guid, 0) + w.WriteString(pkt.AppName, 1) + w.WriteInt64(pkt.LoginType, 2) + w.WriteInt64(pkt.Timestamp, 3) + w.WriteInt64(pkt.NextItemIndex, 4) + w.WriteInt64(pkt.RequireMax, 5) + w.WriteInt64(pkt.GetDevListType, 6) + return w.Bytes() +} + +func (pkt *SvcDevLoginInfo) ToBytes() []byte { + w := NewJceWriter() + return w.Bytes() +} + +func (pkt *DelMsgInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.FromUin, 0) + w.WriteInt64(pkt.MsgTime, 1) + w.WriteInt16(pkt.MsgSeq, 2) + w.WriteBytes(pkt.MsgCookies, 3) + w.WriteInt16(pkt.Cmd, 4) + w.WriteInt64(pkt.MsgType, 5) + w.WriteInt64(pkt.AppId, 6) + w.WriteInt64(pkt.SendTime, 7) + w.WriteInt32(pkt.SsoSeq, 8) + w.WriteInt32(pkt.SsoIp, 9) + w.WriteInt32(pkt.ClientIp, 10) + return w.Bytes() +} + func (pkt *FriendListRequest) ToBytes() []byte { w := NewJceWriter() w.WriteInt32(pkt.Reqtype, 0) @@ -97,6 +451,203 @@ func (pkt *FriendListRequest) ToBytes() []byte { return w.Bytes() } +func (pkt *FriendInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.FriendUin, 0) + w.WriteByte(pkt.GroupId, 1) + w.WriteInt16(pkt.FaceId, 2) + w.WriteString(pkt.Remark, 3) + w.WriteByte(pkt.QQType, 4) + w.WriteByte(pkt.Status, 5) + w.WriteByte(pkt.MemberLevel, 6) + w.WriteByte(pkt.IsMqqOnLine, 7) + w.WriteByte(pkt.QQOnlineState, 8) + w.WriteByte(pkt.IsIphoneOnline, 9) + w.WriteByte(pkt.DetailStatusFlag, 10) + w.WriteByte(pkt.QQOnlineStateV2, 11) + w.WriteString(pkt.ShowName, 12) + w.WriteByte(pkt.IsRemark, 13) + w.WriteString(pkt.Nick, 14) + w.WriteByte(pkt.SpecialFlag, 15) + w.WriteBytes(pkt.IMGroupID, 16) + w.WriteBytes(pkt.MSFGroupID, 17) + w.WriteInt32(pkt.TermType, 18) + w.WriteByte(pkt.Network, 20) + w.WriteBytes(pkt.Ring, 21) + w.WriteInt64(pkt.AbiFlag, 22) + w.WriteInt64(pkt.FaceAddonId, 23) + w.WriteInt32(pkt.NetworkType, 24) + w.WriteInt64(pkt.VipFont, 25) + w.WriteInt32(pkt.IconType, 26) + w.WriteString(pkt.TermDesc, 27) + w.WriteInt64(pkt.ColorRing, 28) + w.WriteByte(pkt.ApolloFlag, 29) + w.WriteInt64(pkt.ApolloTimestamp, 30) + w.WriteByte(pkt.Sex, 31) + w.WriteInt64(pkt.FounderFont, 32) + w.WriteString(pkt.EimId, 33) + w.WriteString(pkt.EimMobile, 34) + w.WriteByte(pkt.OlympicTorch, 35) + w.WriteInt64(pkt.ApolloSignTime, 36) + w.WriteInt64(pkt.LaviUin, 37) + w.WriteInt64(pkt.TagUpdateTime, 38) + w.WriteInt64(pkt.GameLastLoginTime, 39) + w.WriteInt64(pkt.GameAppId, 40) + w.WriteBytes(pkt.CardID, 41) + w.WriteInt64(pkt.BitSet, 42) + w.WriteByte(pkt.KingOfGloryFlag, 43) + w.WriteInt64(pkt.KingOfGloryRank, 44) + w.WriteString(pkt.MasterUin, 45) + w.WriteInt64(pkt.LastMedalUpdateTime, 46) + w.WriteInt64(pkt.FaceStoreId, 47) + w.WriteInt64(pkt.FontEffect, 48) + w.WriteString(pkt.DOVId, 49) + w.WriteInt64(pkt.BothFlag, 50) + w.WriteByte(pkt.CentiShow3DFlag, 51) + w.WriteBytes(pkt.IntimateInfo, 52) + w.WriteByte(pkt.ShowNameplate, 53) + w.WriteByte(pkt.NewLoverDiamondFlag, 54) + w.WriteBytes(pkt.ExtSnsFrdData, 55) + w.WriteBytes(pkt.MutualMarkData, 56) + return w.Bytes() +} + +func (pkt *TroopListRequest) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteByte(pkt.GetMSFMsgFlag, 1) + w.WriteBytes(pkt.Cookies, 2) + w.WriteInt64Slice(pkt.GroupInfo, 3) + w.WriteByte(pkt.GroupFlagExt, 4) + w.WriteInt32(pkt.Version, 5) + w.WriteInt64(pkt.CompanyId, 6) + w.WriteInt64(pkt.VersionNum, 7) + w.WriteByte(pkt.GetLongGroupName, 8) + return w.Bytes() +} + +func (pkt *TroopNumber) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.GroupUin, 0) + w.WriteInt64(pkt.GroupCode, 1) + w.WriteByte(pkt.Flag, 2) + w.WriteInt64(pkt.GroupInfoSeq, 3) + w.WriteString(pkt.GroupName, 4) + w.WriteString(pkt.GroupMemo, 5) + w.WriteInt64(pkt.GroupFlagExt, 6) + w.WriteInt64(pkt.GroupRankSeq, 7) + w.WriteInt64(pkt.CertificationType, 8) + w.WriteInt64(pkt.ShutUpTimestamp, 9) + w.WriteInt64(pkt.MyShutUpTimestamp, 10) + w.WriteInt64(pkt.CmdUinUinFlag, 11) + w.WriteInt64(pkt.AdditionalFlag, 12) + w.WriteInt64(pkt.GroupTypeFlag, 13) + w.WriteInt64(pkt.GroupSecType, 14) + w.WriteInt64(pkt.GroupSecTypeInfo, 15) + w.WriteInt64(pkt.GroupClassExt, 16) + w.WriteInt64(pkt.AppPrivilegeFlag, 17) + w.WriteInt64(pkt.SubscriptionUin, 18) + w.WriteInt64(pkt.MemberNum, 19) + w.WriteInt64(pkt.MemberNumSeq, 20) + w.WriteInt64(pkt.MemberCardSeq, 21) + w.WriteInt64(pkt.GroupFlagExt3, 22) + w.WriteInt64(pkt.GroupOwnerUin, 23) + w.WriteByte(pkt.IsConfGroup, 24) + w.WriteByte(pkt.IsModifyConfGroupFace, 25) + w.WriteByte(pkt.IsModifyConfGroupName, 26) + w.WriteInt64(pkt.CmdUinJoinTime, 27) + w.WriteInt64(pkt.CompanyId, 28) + w.WriteInt64(pkt.MaxGroupMemberNum, 29) + w.WriteInt64(pkt.CmdUinGroupMask, 30) + w.WriteInt64(pkt.GuildAppId, 31) + w.WriteInt64(pkt.GuildSubType, 32) + w.WriteInt64(pkt.CmdUinRingtoneID, 33) + w.WriteInt64(pkt.CmdUinFlagEx2, 34) + return w.Bytes() +} + +func (pkt *TroopMemberListRequest) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt64(pkt.GroupCode, 1) + w.WriteInt64(pkt.NextUin, 2) + w.WriteInt64(pkt.GroupUin, 3) + w.WriteInt64(pkt.Version, 4) + w.WriteInt64(pkt.ReqType, 5) + w.WriteInt64(pkt.GetListAppointTime, 6) + w.WriteByte(pkt.RichCardNameVer, 7) + return w.Bytes() +} + +func (pkt *TroopMemberInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.MemberUin, 0) + w.WriteInt16(pkt.FaceId, 1) + w.WriteByte(pkt.Age, 2) + w.WriteByte(pkt.Gender, 3) + w.WriteString(pkt.Nick, 4) + w.WriteByte(pkt.Status, 5) + w.WriteString(pkt.ShowName, 6) + w.WriteString(pkt.Name, 8) + w.WriteString(pkt.Memo, 12) + w.WriteString(pkt.AutoRemark, 13) + w.WriteInt64(pkt.MemberLevel, 14) + w.WriteInt64(pkt.JoinTime, 15) + w.WriteInt64(pkt.LastSpeakTime, 16) + w.WriteInt64(pkt.CreditLevel, 17) + w.WriteInt64(pkt.Flag, 18) + w.WriteInt64(pkt.FlagExt, 19) + w.WriteInt64(pkt.Point, 20) + w.WriteByte(pkt.Concerned, 21) + w.WriteByte(pkt.Shielded, 22) + w.WriteString(pkt.SpecialTitle, 23) + w.WriteInt64(pkt.SpecialTitleExpireTime, 24) + w.WriteString(pkt.Job, 25) + w.WriteByte(pkt.ApolloFlag, 26) + w.WriteInt64(pkt.ApolloTimestamp, 27) + w.WriteInt64(pkt.GlobalGroupLevel, 28) + w.WriteInt64(pkt.TitleId, 29) + w.WriteInt64(pkt.ShutUpTimestap, 30) + w.WriteInt64(pkt.GlobalGroupPoint, 31) + w.WriteByte(pkt.RichCardNameVer, 33) + w.WriteInt64(pkt.VipType, 34) + w.WriteInt64(pkt.VipLevel, 35) + w.WriteInt64(pkt.BigClubLevel, 36) + w.WriteInt64(pkt.BigClubFlag, 37) + w.WriteInt64(pkt.Nameplate, 38) + w.WriteBytes(pkt.GroupHonor, 39) + return w.Bytes() +} + +func (pkt *ModifyGroupCardRequest) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Zero, 0) + w.WriteInt64(pkt.GroupCode, 1) + w.WriteInt64(pkt.NewSeq, 2) + w.writeHead(9, 3) + if len(pkt.UinInfo) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UinInfo)), 0) + for _, i := range pkt.UinInfo { + w.buf.Write(i.ToBytes()) + } + } + return w.Bytes() +} + +func (pkt *UinInfo) ToBytes() []byte { + w := NewJceWriter() + w.WriteInt64(pkt.Uin, 0) + w.WriteInt64(pkt.Flag, 1) + w.WriteString(pkt.Name, 2) + w.WriteByte(pkt.Gender, 3) + w.WriteString(pkt.Phone, 4) + w.WriteString(pkt.Email, 5) + w.WriteString(pkt.Remark, 6) + return w.Bytes() +} + func (pkt *SummaryCardReq) ToBytes() []byte { w := NewJceWriter() w.WriteInt64(pkt.Uin, 0) @@ -127,74 +678,6 @@ func (pkt *SummaryCardReqSearch) ToBytes() []byte { return w.Bytes() } -func (pkt *TroopListRequest) ToBytes() []byte { - w := NewJceWriter() - w.WriteInt64(pkt.Uin, 0) - w.WriteByte(pkt.GetMSFMsgFlag, 1) - w.WriteBytes(pkt.Cookies, 2) - w.WriteInt64Slice(pkt.GroupInfo, 3) - w.WriteByte(pkt.GroupFlagExt, 4) - w.WriteInt32(pkt.Version, 5) - w.WriteInt64(pkt.CompanyId, 6) - w.WriteInt64(pkt.VersionNum, 7) - w.WriteByte(pkt.GetLongGroupName, 8) - return w.Bytes() -} - -func (pkt *TroopMemberListRequest) ToBytes() []byte { - w := NewJceWriter() - w.WriteInt64(pkt.Uin, 0) - w.WriteInt64(pkt.GroupCode, 1) - w.WriteInt64(pkt.NextUin, 2) - w.WriteInt64(pkt.GroupUin, 3) - w.WriteInt64(pkt.Version, 4) - w.WriteInt64(pkt.ReqType, 5) - w.WriteInt64(pkt.GetListAppointTime, 6) - w.WriteByte(pkt.RichCardNameVer, 7) - return w.Bytes() -} - -func (pkt *SvcRespPushMsg) ToBytes() []byte { - w := NewJceWriter() - w.WriteInt64(pkt.Uin, 0) - w.WriteJceStructSlice(pkt.DelInfos, 1) - w.WriteInt32(pkt.Svrip, 2) - w.WriteBytes(pkt.PushToken, 3) - w.WriteInt32(pkt.ServiceType, 4) - return w.Bytes() -} - -func (pkt *ModifyGroupCardRequest) ToBytes() []byte { - w := NewJceWriter() - w.WriteInt64(pkt.Zero, 0) - w.WriteInt64(pkt.GroupCode, 1) - w.WriteInt64(pkt.NewSeq, 2) - w.WriteJceStructSlice(pkt.UinInfo, 3) - return w.Bytes() -} - -func (pkt *SvcReqGetDevLoginInfo) ToBytes() []byte { - w := NewJceWriter() - w.WriteBytes(pkt.Guid, 0) - w.WriteString(pkt.AppName, 1) - w.WriteInt64(pkt.LoginType, 2) - w.WriteInt64(pkt.Timestamp, 3) - w.WriteInt64(pkt.NextItemIndex, 4) - w.WriteInt64(pkt.RequireMax, 5) - w.WriteInt64(pkt.GetDevListType, 6) - return w.Bytes() -} - -func (pkt *SvcReqRegisterNew) ToBytes() []byte { - w := NewJceWriter() - w.WriteInt64(pkt.RequestOptional, 0) - w.WriteByte(pkt.DisGroupMsgFilter, 14) - w.WriteByte(pkt.GroupMask, 15) - w.WriteInt64(pkt.EndSeq, 16) - w.WriteBytes(pkt.O769Body, 20) - return w.Bytes() -} - func (pkt *DelFriendReq) ToBytes() []byte { w := NewJceWriter() w.WriteInt64(pkt.Uin, 0) diff --git a/binary/jce/writer.go b/binary/jce/writer.go index 6feae89e..d5d803c8 100644 --- a/binary/jce/writer.go +++ b/binary/jce/writer.go @@ -4,9 +4,6 @@ import ( "bytes" goBinary "encoding/binary" "math" - "reflect" - "strconv" - "sync" ) type JceWriter struct { @@ -166,68 +163,6 @@ func (w *JceWriter) WriteBytesSlice(l [][]byte, tag byte) { } } -func (w *JceWriter) WriteSlice(i interface{}, tag byte) { - va := reflect.ValueOf(i) - if va.Kind() != reflect.Slice { - panic("JceWriter.WriteSlice: not a slice") - } - w.writeSlice(va, tag) -} - -func (w *JceWriter) writeSlice(slice reflect.Value, tag byte) { - if slice.Kind() != reflect.Slice { - return - } - w.writeHead(9, tag) - if slice.Len() == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - return - } - w.WriteInt32(int32(slice.Len()), 0) - for i := 0; i < slice.Len(); i++ { - v := slice.Index(i) - w.writeObject(v, 0) - } -} - -func (w *JceWriter) WriteJceStructSlice(l []IJceStruct, tag byte) { - w.writeHead(9, tag) - if len(l) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - return - } - w.WriteInt32(int32(len(l)), 0) - for _, v := range l { - w.WriteJceStruct(v, 0) - } -} - -func (w *JceWriter) WriteMap(m interface{}, tag byte) { - va := reflect.ValueOf(m) - if va.Kind() != reflect.Map { - panic("JceWriter.WriteMap: not a map") - } - w.writeMap(va, tag) -} - -func (w *JceWriter) writeMap(m reflect.Value, tag byte) { - if m.IsNil() { - w.writeHead(8, tag) - w.writeHead(12, 0) // w.WriteInt32(0, 0) - return - } - if m.Kind() != reflect.Map { - return - } - w.writeHead(8, tag) - w.WriteInt32(int32(m.Len()), 0) - iter := m.MapRange() - for iter.Next() { - w.writeObject(iter.Key(), 0) - w.writeObject(iter.Value(), 1) - } -} - func (w *JceWriter) writeMapStrStr(m map[string]string, tag byte) { if m == nil { w.writeHead(8, tag) @@ -270,105 +205,6 @@ func (w *JceWriter) writeMapStrMapStrBytes(m map[string]map[string][]byte, tag b } } -func (w *JceWriter) writeObject(v reflect.Value, tag byte) { - k := v.Kind() - if k == reflect.Map { - switch o := v.Interface().(type) { - case map[string]string: - w.writeMapStrStr(o, tag) - case map[string][]byte: - w.writeMapStrBytes(o, tag) - case map[string]map[string][]byte: - w.writeMapStrMapStrBytes(o, tag) - default: - w.writeMap(v, tag) - } - return - } - if k == reflect.Slice { - switch o := v.Interface().(type) { - case []byte: - w.WriteBytes(o, tag) - case []IJceStruct: - w.WriteJceStructSlice(o, tag) - default: - w.writeSlice(v, tag) - } - return - } - switch k { - case reflect.Uint8, reflect.Int8: - w.WriteByte(*(*byte)(pointerOf(v)), tag) - case reflect.Uint16, reflect.Int16: - w.WriteInt16(*(*int16)(pointerOf(v)), tag) - case reflect.Uint32, reflect.Int32: - w.WriteInt32(*(*int32)(pointerOf(v)), tag) - case reflect.Uint64, reflect.Int64: - w.WriteInt64(*(*int64)(pointerOf(v)), tag) - case reflect.String: - w.WriteString(v.String(), tag) - default: - switch o := v.Interface().(type) { - case IJceStruct: - w.WriteJceStruct(o, tag) - case float32: - w.WriteFloat32(o, tag) - case float64: - w.WriteFloat64(o, tag) - } - } -} - -type decoder struct { - index int - id int -} - -var decoderCache = sync.Map{} - -// WriteJceStructRaw 写入 Jce 结构体 -func (w *JceWriter) WriteJceStructRaw(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, - }) - } - decoderCache.Store(t, jceDec) // 存入缓存 - } - for _, dec := range jceDec { - obj := v.Field(dec.index) - w.writeObject(obj, byte(dec.id)) - } -} - -func (w *JceWriter) WriteJceStruct(s IJceStruct, tag byte) { - w.writeHead(10, tag) - w.WriteJceStructRaw(s) - w.writeHead(11, 0) -} - func (w *JceWriter) Bytes() []byte { return w.buf.Bytes() }