github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/internal/proto/dynamic.go (about) 1 package proto 2 3 import ( 4 "encoding/binary" 5 "math" 6 "sort" 7 ) 8 9 type DynamicMessage map[uint64]any 10 11 // zigzag encoding types 12 type ( 13 SInt int 14 SInt32 int32 15 SInt64 int64 16 ) 17 18 type encoder struct { 19 buf []byte 20 } 21 22 func (msg DynamicMessage) Encode() []byte { 23 en := encoder{} 24 25 // sort all items 26 type pair struct { 27 key uint64 28 value any 29 } 30 all := make([]pair, len(msg)) 31 for k, v := range msg { 32 all = append(all, pair{key: k, value: v}) 33 } 34 sort.Slice(all, func(i, j int) bool { 35 return all[i].key < all[j].key 36 }) 37 38 //nolint:staticcheck 39 for _, item := range all { 40 key := item.key << 3 41 switch v := item.value.(type) { 42 case bool: 43 en.uvarint(key | 0) 44 vi := uint64(0) 45 if v { 46 vi = 1 47 } 48 en.uvarint(vi) 49 case int: 50 en.uvarint(key | 0) 51 en.uvarint(uint64(v)) 52 case uint: 53 en.uvarint(key | 0) 54 en.uvarint(uint64(v)) 55 case int32: 56 en.uvarint(key | 0) 57 en.uvarint(uint64(v)) 58 case int64: 59 en.uvarint(key | 0) 60 en.uvarint(uint64(v)) 61 case uint32: 62 en.uvarint(key | 0) 63 en.uvarint(uint64(v)) 64 case uint64: 65 en.uvarint(key | 0) 66 en.uvarint(v) 67 case SInt: 68 en.uvarint(key | 0) 69 en.svarint(int64(v)) 70 case SInt32: 71 en.uvarint(key | 0) 72 en.svarint(int64(v)) 73 case SInt64: 74 en.uvarint(key | 0) 75 en.svarint(int64(v)) 76 case float32: 77 en.uvarint(key | 5) 78 en.u32(math.Float32bits(v)) 79 case float64: 80 en.uvarint(key | 1) 81 en.u64(math.Float64bits(v)) 82 case string: 83 en.uvarint(key | 2) 84 en.uvarint(uint64(len(v))) 85 en.buf = append(en.buf, v...) 86 case []uint64: 87 for i := 0; i < len(v); i++ { 88 en.uvarint(key | 0) 89 en.uvarint(v[i]) 90 } 91 case []byte: 92 en.uvarint(key | 2) 93 en.uvarint(uint64(len(v))) 94 en.buf = append(en.buf, v...) 95 case DynamicMessage: 96 en.uvarint(key | 2) 97 b := v.Encode() 98 en.uvarint(uint64(len(b))) 99 en.buf = append(en.buf, b...) 100 } 101 } 102 return en.buf 103 } 104 105 func (en *encoder) uvarint(v uint64) { 106 en.buf = binary.AppendUvarint(en.buf, v) 107 } 108 109 func (en *encoder) svarint(v int64) { 110 en.buf = binary.AppendVarint(en.buf, v) 111 } 112 113 func (en *encoder) u32(v uint32) { 114 en.buf = binary.LittleEndian.AppendUint32(en.buf, v) 115 } 116 117 func (en *encoder) u64(v uint64) { 118 en.buf = binary.LittleEndian.AppendUint64(en.buf, v) 119 }