Skip to content

Commit 456a01a

Browse files
blixtbradfitz
authored andcommitted
encoding/binary: add bool support
This change adds support for decoding and encoding the bool type. The encoding is a single byte, with a zero value for false and a non-zero value for true. Closes golang#16856. Change-Id: I1d1114b320263691473bb100cad0f380e0204186 Reviewed-on: https://go-review.googlesource.com/28514 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
1 parent 5e7bae5 commit 456a01a

File tree

2 files changed

+85
-8
lines changed

2 files changed

+85
-8
lines changed

src/encoding/binary/binary.go

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
169169
return err
170170
}
171171
switch data := data.(type) {
172+
case *bool:
173+
*data = b[0] != 0
172174
case *int8:
173175
*data = int8(b[0])
174176
case *uint8:
@@ -185,8 +187,12 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
185187
*data = int64(order.Uint64(bs))
186188
case *uint64:
187189
*data = order.Uint64(bs)
188-
case []int8:
190+
case []bool:
189191
for i, x := range bs { // Easier to loop over the input for 8-bit values.
192+
data[i] = x != 0
193+
}
194+
case []int8:
195+
for i, x := range bs {
190196
data[i] = int8(x)
191197
}
192198
case []uint8:
@@ -258,6 +264,26 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
258264
bs = b[:n]
259265
}
260266
switch v := data.(type) {
267+
case *bool:
268+
if *v {
269+
b[0] = 1
270+
} else {
271+
b[0] = 0
272+
}
273+
case bool:
274+
if v {
275+
b[0] = 1
276+
} else {
277+
b[0] = 0
278+
}
279+
case []bool:
280+
for i, x := range v {
281+
if x {
282+
bs[i] = 1
283+
} else {
284+
bs[i] = 0
285+
}
286+
}
261287
case *int8:
262288
b[0] = byte(*v)
263289
case int8:
@@ -378,7 +404,8 @@ func sizeof(t reflect.Type) int {
378404
}
379405
return sum
380406

381-
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
407+
case reflect.Bool,
408+
reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
382409
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
383410
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
384411
return int(t.Size())
@@ -395,6 +422,21 @@ type coder struct {
395422
type decoder coder
396423
type encoder coder
397424

425+
func (d *decoder) bool() bool {
426+
x := d.buf[0]
427+
d.buf = d.buf[1:]
428+
return x != 0
429+
}
430+
431+
func (e *encoder) bool(x bool) {
432+
if x {
433+
e.buf[0] = 1
434+
} else {
435+
e.buf[0] = 0
436+
}
437+
e.buf = e.buf[1:]
438+
}
439+
398440
func (d *decoder) uint8() uint8 {
399441
x := d.buf[0]
400442
d.buf = d.buf[1:]
@@ -485,6 +527,9 @@ func (d *decoder) value(v reflect.Value) {
485527
d.value(v.Index(i))
486528
}
487529

530+
case reflect.Bool:
531+
v.SetBool(d.bool())
532+
488533
case reflect.Int8:
489534
v.SetInt(int64(d.int8()))
490535
case reflect.Int16:
@@ -547,6 +592,9 @@ func (e *encoder) value(v reflect.Value) {
547592
e.value(v.Index(i))
548593
}
549594

595+
case reflect.Bool:
596+
e.bool(v.Bool())
597+
550598
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
551599
switch v.Type().Kind() {
552600
case reflect.Int8:
@@ -609,7 +657,7 @@ func (e *encoder) skip(v reflect.Value) {
609657
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
610658
func intDataSize(data interface{}) int {
611659
switch data := data.(type) {
612-
case int8, uint8, *int8, *uint8:
660+
case bool, int8, uint8, *bool, *int8, *uint8:
613661
return 1
614662
case []int8:
615663
return len(data)

src/encoding/binary/binary_test.go

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ type Struct struct {
2727
Complex64 complex64
2828
Complex128 complex128
2929
Array [4]uint8
30+
Bool bool
31+
BoolArray [4]bool
3032
}
3133

3234
type T struct {
@@ -58,6 +60,9 @@ var s = Struct{
5860
),
5961

6062
[4]uint8{0x43, 0x44, 0x45, 0x46},
63+
64+
true,
65+
[4]bool{true, false, true, false},
6166
}
6267

6368
var big = []byte{
@@ -76,6 +81,9 @@ var big = []byte{
7681
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
7782

7883
67, 68, 69, 70,
84+
85+
1,
86+
1, 0, 1, 0,
7987
}
8088

8189
var little = []byte{
@@ -94,6 +102,9 @@ var little = []byte{
94102
58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59,
95103

96104
67, 68, 69, 70,
105+
106+
1,
107+
1, 0, 1, 0,
97108
}
98109

99110
var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
@@ -141,6 +152,25 @@ func TestWriteSlice(t *testing.T) {
141152
checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
142153
}
143154

155+
func TestReadBool(t *testing.T) {
156+
var res bool
157+
var err error
158+
err = Read(bytes.NewReader([]byte{0}), BigEndian, &res)
159+
checkResult(t, "ReadBool", BigEndian, err, res, false)
160+
res = false
161+
err = Read(bytes.NewReader([]byte{1}), BigEndian, &res)
162+
checkResult(t, "ReadBool", BigEndian, err, res, true)
163+
res = false
164+
err = Read(bytes.NewReader([]byte{2}), BigEndian, &res)
165+
checkResult(t, "ReadBool", BigEndian, err, res, true)
166+
}
167+
168+
func TestReadBoolSlice(t *testing.T) {
169+
slice := make([]bool, 4)
170+
err := Read(bytes.NewReader([]byte{0, 1, 2, 255}), BigEndian, slice)
171+
checkResult(t, "ReadBoolSlice", BigEndian, err, slice, []bool{false, true, true, true})
172+
}
173+
144174
// Addresses of arrays are easier to manipulate with reflection than are slices.
145175
var intArrays = []interface{}{
146176
&[100]int8{},
@@ -422,16 +452,15 @@ func BenchmarkReadInts(b *testing.B) {
422452
Read(r, BigEndian, &ls.Uint32)
423453
Read(r, BigEndian, &ls.Uint64)
424454
}
425-
455+
b.StopTimer()
426456
want := s
427457
want.Float32 = 0
428458
want.Float64 = 0
429459
want.Complex64 = 0
430460
want.Complex128 = 0
431-
for i := range want.Array {
432-
want.Array[i] = 0
433-
}
434-
b.StopTimer()
461+
want.Array = [4]uint8{0, 0, 0, 0}
462+
want.Bool = false
463+
want.BoolArray = [4]bool{false, false, false, false}
435464
if b.N > 0 && !reflect.DeepEqual(ls, want) {
436465
b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
437466
}

0 commit comments

Comments
 (0)