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