Skip to content

Commit 801ef65

Browse files
author
Lemmer El Assal
committed
More convenient parsing of little-endian data (e.g.: when wanting to make a uint32 from a slice of 3 bytes.
1 parent 7a6da21 commit 801ef65

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

src/encoding/binary/binary.go

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,15 @@ var BigEndian bigEndian
4949
type littleEndian struct{}
5050

5151
func (littleEndian) Uint16(b []byte) uint16 {
52-
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
53-
return uint16(b[0]) | uint16(b[1])<<8
52+
// The previous implementation wouldn't allow an empty slice
53+
switch len(b) {
54+
case 0:
55+
return 0
56+
case 1:
57+
return uint16(b[0])
58+
default:
59+
return uint16(b[0]) | uint16(b[1])<<8
60+
}
5461
}
5562

5663
func (littleEndian) PutUint16(b []byte, v uint16) {
@@ -60,8 +67,19 @@ func (littleEndian) PutUint16(b []byte, v uint16) {
6067
}
6168

6269
func (littleEndian) Uint32(b []byte) uint32 {
63-
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
64-
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
70+
// The previous implementation wouldn't allow for example a 3 byte slice
71+
switch len(b) {
72+
case 0:
73+
return 0
74+
case 1:
75+
return uint32(b[0])
76+
case 2:
77+
return uint32(b[0]) | uint32(b[1])<<8
78+
case 3:
79+
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16
80+
default:
81+
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
82+
}
6583
}
6684

6785
func (littleEndian) PutUint32(b []byte, v uint32) {
@@ -73,9 +91,30 @@ func (littleEndian) PutUint32(b []byte, v uint32) {
7391
}
7492

7593
func (littleEndian) Uint64(b []byte) uint64 {
76-
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
77-
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
78-
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
94+
switch len(b) {
95+
case 0:
96+
return 0
97+
case 1:
98+
return uint64(b[0])
99+
case 2:
100+
return uint64(b[0]) | uint64(b[1])<<8
101+
case 3:
102+
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16
103+
case 4:
104+
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
105+
case 5:
106+
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
107+
uint64(b[4])<<32
108+
case 6:
109+
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
110+
uint64(b[4])<<32 | uint64(b[5])<<40
111+
case 7:
112+
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
113+
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48
114+
default:
115+
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
116+
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
117+
}
79118
}
80119

81120
func (littleEndian) PutUint64(b []byte, v uint64) {

src/encoding/binary/binary_test.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -370,15 +370,6 @@ func TestReadTruncated(t *testing.T) {
370370
}
371371
}
372372

373-
func testUint64SmallSliceLengthPanics() (panicked bool) {
374-
defer func() {
375-
panicked = recover() != nil
376-
}()
377-
b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
378-
LittleEndian.Uint64(b[:4])
379-
return false
380-
}
381-
382373
func testPutUint64SmallSliceLengthPanics() (panicked bool) {
383374
defer func() {
384375
panicked = recover() != nil
@@ -389,9 +380,6 @@ func testPutUint64SmallSliceLengthPanics() (panicked bool) {
389380
}
390381

391382
func TestEarlyBoundsChecks(t *testing.T) {
392-
if testUint64SmallSliceLengthPanics() != true {
393-
t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't")
394-
}
395383
if testPutUint64SmallSliceLengthPanics() != true {
396384
t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't")
397385
}

0 commit comments

Comments
 (0)