github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/binary/jce/writer.go (about) 1 package jce 2 3 import ( 4 "bytes" 5 goBinary "encoding/binary" 6 "math" 7 ) 8 9 type JceWriter struct { 10 buf *bytes.Buffer 11 } 12 13 func NewJceWriter() *JceWriter { 14 return &JceWriter{buf: new(bytes.Buffer)} 15 } 16 17 func (w *JceWriter) writeHead(t, tag byte) { 18 if tag < 0xF { 19 w.buf.WriteByte(tag<<4 | t) 20 } else { 21 w.buf.WriteByte(0xF0 | t) 22 w.buf.WriteByte(tag) 23 } 24 } 25 26 func (w *JceWriter) WriteByte(b, tag byte) *JceWriter { 27 if b == 0 { 28 w.writeHead(12, tag) 29 } else { 30 w.writeHead(0, tag) 31 w.buf.WriteByte(b) 32 } 33 return w 34 } 35 36 func (w *JceWriter) WriteBool(b bool, tag byte) { 37 var by byte 38 if b { 39 by = 1 40 } 41 w.WriteByte(by, tag) 42 } 43 44 func (w *JceWriter) WriteInt16(n int16, tag byte) { 45 switch { 46 case n >= -128 && n <= 127: 47 w.WriteByte(byte(n), tag) 48 default: 49 w.putInt16(n, tag) 50 } 51 } 52 53 //go:nosplit 54 func (w *JceWriter) putInt16(n int16, tag byte) { 55 w.writeHead(1, tag) 56 var buf [2]byte 57 goBinary.BigEndian.PutUint16(buf[:], uint16(n)) 58 w.buf.Write(buf[:]) 59 } 60 61 func (w *JceWriter) WriteInt32(n int32, tag byte) *JceWriter { 62 switch { 63 case n >= -128 && n <= 127: 64 w.WriteByte(byte(n), tag) 65 case n >= -32768 && n <= 32767: 66 w.putInt16(int16(n), tag) 67 default: 68 w.putInt32(n, tag) 69 } 70 return w 71 } 72 73 //go:nosplit 74 func (w *JceWriter) putInt32(n int32, tag byte) { 75 w.writeHead(2, tag) 76 var buf [4]byte 77 goBinary.BigEndian.PutUint32(buf[:], uint32(n)) 78 w.buf.Write(buf[:]) 79 } 80 81 func (w *JceWriter) WriteInt64(n int64, tag byte) *JceWriter { 82 switch { 83 case n >= -128 && n <= 127: 84 w.WriteByte(byte(n), tag) 85 case n >= -32768 && n <= 32767: 86 w.putInt16(int16(n), tag) 87 case n >= -2147483648 && n <= 2147483647: 88 w.putInt32(int32(n), tag) 89 default: 90 w.putInt64(n, tag) 91 } 92 return w 93 } 94 95 //go:nosplit 96 func (w *JceWriter) putInt64(n int64, tag byte) { 97 w.writeHead(3, tag) 98 var buf [8]byte 99 goBinary.BigEndian.PutUint64(buf[:], uint64(n)) 100 w.buf.Write(buf[:]) 101 } 102 103 //go:nosplit 104 func (w *JceWriter) WriteFloat32(n float32, tag byte) { 105 w.writeHead(4, tag) 106 var buf [4]byte 107 goBinary.BigEndian.PutUint32(buf[:], math.Float32bits(n)) 108 w.buf.Write(buf[:]) 109 } 110 111 //go:nosplit 112 func (w *JceWriter) WriteFloat64(n float64, tag byte) { 113 w.writeHead(5, tag) 114 var buf [8]byte 115 goBinary.BigEndian.PutUint64(buf[:], math.Float64bits(n)) 116 w.buf.Write(buf[:]) 117 } 118 119 func (w *JceWriter) WriteString(s string, tag byte) *JceWriter { 120 if len(s) > 255 { 121 w.writeHead(7, tag) 122 var buf [4]byte 123 goBinary.BigEndian.PutUint32(buf[:], uint32(len(s))) 124 w.buf.Write(buf[:]) 125 w.buf.WriteString(s) 126 return w 127 } 128 w.writeHead(6, tag) 129 w.buf.WriteByte(byte(len(s))) 130 w.buf.WriteString(s) 131 return w 132 } 133 134 func (w *JceWriter) WriteBytes(l []byte, tag byte) *JceWriter { 135 w.writeHead(13, tag) 136 w.buf.WriteByte(0) // w.writeHead(0, 0) 137 w.WriteInt32(int32(len(l)), 0) 138 w.buf.Write(l) 139 return w 140 } 141 142 func (w *JceWriter) WriteInt64Slice(l []int64, tag byte) { 143 w.writeHead(9, tag) 144 if len(l) == 0 { 145 w.writeHead(12, 0) // w.WriteInt32(0, 0) 146 return 147 } 148 w.WriteInt32(int32(len(l)), 0) 149 for _, v := range l { 150 w.WriteInt64(v, 0) 151 } 152 } 153 154 func (w *JceWriter) WriteBytesSlice(l [][]byte, tag byte) { 155 w.writeHead(9, tag) 156 if len(l) == 0 { 157 w.writeHead(12, 0) // w.WriteInt32(0, 0) 158 return 159 } 160 w.WriteInt32(int32(len(l)), 0) 161 for _, v := range l { 162 w.WriteBytes(v, 0) 163 } 164 } 165 166 func (w *JceWriter) writeMapStrStr(m map[string]string, tag byte) { 167 if m == nil { 168 w.writeHead(8, tag) 169 w.writeHead(12, 0) // w.WriteInt32(0, 0) 170 return 171 } 172 w.writeHead(8, tag) 173 w.WriteInt32(int32(len(m)), 0) 174 for k, v := range m { 175 w.WriteString(k, 0) 176 w.WriteString(v, 1) 177 } 178 } 179 180 func (w *JceWriter) writeMapStrBytes(m map[string][]byte, tag byte) { 181 if m == nil { 182 w.writeHead(8, tag) 183 w.writeHead(12, 0) // w.WriteInt32(0, 0) 184 return 185 } 186 w.writeHead(8, tag) 187 w.WriteInt32(int32(len(m)), 0) 188 for k, v := range m { 189 w.WriteString(k, 0) 190 w.WriteBytes(v, 1) 191 } 192 } 193 194 func (w *JceWriter) writeMapStrMapStrBytes(m map[string]map[string][]byte, tag byte) { 195 if m == nil { 196 w.writeHead(8, tag) 197 w.writeHead(12, 0) // w.WriteInt32(0, 0) 198 return 199 } 200 w.writeHead(8, tag) 201 w.WriteInt32(int32(len(m)), 0) 202 for k, v := range m { 203 w.WriteString(k, 0) 204 w.writeMapStrBytes(v, 1) 205 } 206 } 207 208 func (w *JceWriter) Bytes() []byte { 209 return w.buf.Bytes() 210 }