1
1
package packet
2
2
3
3
import (
4
+ "encoding/binary"
4
5
"errors"
5
6
"io"
6
7
"math"
@@ -175,8 +176,9 @@ func (u *UnsignedByte) ReadFrom(r io.Reader) (n int64, err error) {
175
176
}
176
177
177
178
func (s Short ) WriteTo (w io.Writer ) (int64 , error ) {
178
- n := uint16 (s )
179
- nn , err := w .Write ([]byte {byte (n >> 8 ), byte (n )})
179
+ var buf [2 ]byte
180
+ binary .BigEndian .PutUint16 (buf [:], uint16 (s ))
181
+ nn , err := w .Write (buf [:])
180
182
return int64 (nn ), err
181
183
}
182
184
@@ -188,13 +190,14 @@ func (s *Short) ReadFrom(r io.Reader) (n int64, err error) {
188
190
n += int64 (nn )
189
191
}
190
192
191
- * s = Short (int16 (bs [0 ]) << 8 | int16 ( bs [ 1 ]))
193
+ * s = Short (binary . BigEndian . Uint16 (bs [: ]))
192
194
return
193
195
}
194
196
195
197
func (us UnsignedShort ) WriteTo (w io.Writer ) (int64 , error ) {
196
- n := uint16 (us )
197
- nn , err := w .Write ([]byte {byte (n >> 8 ), byte (n )})
198
+ var buf [2 ]byte
199
+ binary .BigEndian .PutUint16 (buf [:], uint16 (us ))
200
+ nn , err := w .Write (buf [:])
198
201
return int64 (nn ), err
199
202
}
200
203
@@ -206,13 +209,14 @@ func (us *UnsignedShort) ReadFrom(r io.Reader) (n int64, err error) {
206
209
n += int64 (nn )
207
210
}
208
211
209
- * us = UnsignedShort (int16 (bs [0 ]) << 8 | int16 ( bs [ 1 ]))
212
+ * us = UnsignedShort (binary . BigEndian . Uint16 (bs [: ]))
210
213
return
211
214
}
212
215
213
216
func (i Int ) WriteTo (w io.Writer ) (int64 , error ) {
214
- n := uint32 (i )
215
- nn , err := w .Write ([]byte {byte (n >> 24 ), byte (n >> 16 ), byte (n >> 8 ), byte (n )})
217
+ var buf [4 ]byte
218
+ binary .BigEndian .PutUint32 (buf [:], uint32 (i ))
219
+ nn , err := w .Write (buf [:])
216
220
return int64 (nn ), err
217
221
}
218
222
@@ -224,16 +228,14 @@ func (i *Int) ReadFrom(r io.Reader) (n int64, err error) {
224
228
n += int64 (nn )
225
229
}
226
230
227
- * i = Int (int32 (bs [0 ]) << 24 | int32 ( bs [ 1 ]) << 16 | int32 ( bs [ 2 ]) << 8 | int32 ( bs [ 3 ]))
231
+ * i = Int (binary . BigEndian . Uint32 (bs [: ]))
228
232
return
229
233
}
230
234
231
235
func (l Long ) WriteTo (w io.Writer ) (int64 , error ) {
232
- n := uint64 (l )
233
- nn , err := w .Write ([]byte {
234
- byte (n >> 56 ), byte (n >> 48 ), byte (n >> 40 ), byte (n >> 32 ),
235
- byte (n >> 24 ), byte (n >> 16 ), byte (n >> 8 ), byte (n ),
236
- })
236
+ var buf [8 ]byte
237
+ binary .BigEndian .PutUint64 (buf [:], uint64 (l ))
238
+ nn , err := w .Write (buf [:])
237
239
return int64 (nn ), err
238
240
}
239
241
@@ -245,8 +247,7 @@ func (l *Long) ReadFrom(r io.Reader) (n int64, err error) {
245
247
n += int64 (nn )
246
248
}
247
249
248
- * l = Long (int64 (bs [0 ])<< 56 | int64 (bs [1 ])<< 48 | int64 (bs [2 ])<< 40 | int64 (bs [3 ])<< 32 |
249
- int64 (bs [4 ])<< 24 | int64 (bs [5 ])<< 16 | int64 (bs [6 ])<< 8 | int64 (bs [7 ]))
250
+ * l = Long (binary .BigEndian .Uint64 (bs [:]))
250
251
return
251
252
}
252
253
@@ -260,36 +261,48 @@ func (v VarInt) WriteTo(w io.Writer) (n int64, err error) {
260
261
// WriteToBytes encodes the VarInt into buf and returns the number of bytes written.
261
262
// If the buffer is too small, WriteToBytes will panic.
262
263
func (v VarInt ) WriteToBytes (buf []byte ) int {
264
+ // https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/
263
265
num := uint32 (v )
264
- i := 0
265
- for {
266
- b := num & 0x7F
267
- num >>= 7
268
- if num != 0 {
269
- b |= 0x80
270
- }
271
- buf [i ] = byte (b )
272
- i ++
273
- if num == 0 {
274
- break
275
- }
266
+ if num & 0xFFFFFF80 == 0 {
267
+ buf [0 ] = byte (num )
268
+ return 1
269
+ } else if num & 0xFFFFC000 == 0 {
270
+ result := uint16 ((num & 0x7F | 0x80 )<< 8 | (num >> 7 ))
271
+ binary .BigEndian .PutUint16 (buf , result )
272
+ return 2
273
+ } else if num & 0xFFE00000 == 0 {
274
+ buf [2 ] = byte (num >> 14 )
275
+ startingBytes := uint16 ((num & 0x7F | 0x80 )<< 8 | ((num >> 7 )& 0x7F | 0x80 ))
276
+ binary .BigEndian .PutUint16 (buf , startingBytes )
277
+ return 3
278
+ } else if num & 0xF0000000 == 0 {
279
+ result := (num & 0x7F | 0x80 )<< 24 | (((num >> 7 )& 0x7F | 0x80 ) << 16 ) |
280
+ ((num >> 14 )& 0x7F | 0x80 )<< 8 | (num >> 21 )
281
+ binary .BigEndian .PutUint32 (buf , result )
282
+ return 4
283
+ } else {
284
+ buf [4 ] = byte (num >> 28 )
285
+ startingBytes := (num & 0x7F | 0x80 )<< 24 | ((num >> 7 )& 0x7F | 0x80 )<< 16 |
286
+ ((num >> 14 )& 0x7F | 0x80 )<< 8 | ((num >> 21 )& 0x7F | 0x80 )
287
+ binary .BigEndian .PutUint32 (buf , startingBytes )
288
+ return 5
276
289
}
277
- return i
278
290
}
279
291
280
292
func (v * VarInt ) ReadFrom (r io.Reader ) (n int64 , err error ) {
281
293
var V uint32
282
- var num , n2 int64
294
+ var num int64
295
+ byteReader := CreateByteReader (r )
283
296
for sec := byte (0x80 ); sec & 0x80 != 0 ; num ++ {
284
297
if num > MaxVarIntLen {
285
298
return n , errors .New ("VarInt is too big" )
286
299
}
287
300
288
- n2 , sec , err = readByte (r )
289
- n += n2
301
+ sec , err = byteReader .ReadByte ()
290
302
if err != nil {
291
303
return n , err
292
304
}
305
+ n += 1
293
306
294
307
V |= uint32 (sec & 0x7F ) << uint32 (7 * num )
295
308
}
@@ -326,35 +339,32 @@ func (v VarLong) WriteTo(w io.Writer) (n int64, err error) {
326
339
// WriteToBytes encodes the VarLong into buf and returns the number of bytes written.
327
340
// If the buffer is too small, WriteToBytes will panic.
328
341
func (v VarLong ) WriteToBytes (buf []byte ) int {
342
+ // Like VarInt, but we don't unroll the loop because it might be too long.
329
343
num := uint64 (v )
330
- i := 0
331
- for {
332
- b := num & 0x7F
344
+ n := v .Len ()
345
+ continuationBytes := n - 1
346
+ _ = buf [continuationBytes ] // bounds check hint to compiler; see golang.org/issue/14808
347
+ for i := 0 ; i < continuationBytes ; i ++ {
348
+ buf [i ] = byte (num & 0x7F | 0x80 )
333
349
num >>= 7
334
- if num != 0 {
335
- b |= 0x80
336
- }
337
- buf [i ] = byte (b )
338
- i ++
339
- if num == 0 {
340
- break
341
- }
342
350
}
343
- return i
351
+ buf [continuationBytes ] = byte (num )
352
+ return n
344
353
}
345
354
346
355
func (v * VarLong ) ReadFrom (r io.Reader ) (n int64 , err error ) {
347
356
var V uint64
348
- var num , n2 int64
357
+ var num int64
358
+ byteReader := CreateByteReader (r )
349
359
for sec := byte (0x80 ); sec & 0x80 != 0 ; num ++ {
350
360
if num >= MaxVarLongLen {
351
361
return n , errors .New ("VarLong is too big" )
352
362
}
353
- n2 , sec , err = readByte (r )
354
- n += n2
363
+ sec , err = byteReader .ReadByte ()
355
364
if err != nil {
356
365
return
357
366
}
367
+ n += 1
358
368
359
369
V |= uint64 (sec & 0x7F ) << uint64 (7 * num )
360
370
}
0 commit comments