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  }