Skip to content

Commit df96ff1

Browse files
committed
Add Buffer.Bytes() and Buffer.RawBytes().
1 parent 0a32e3e commit df96ff1

3 files changed

Lines changed: 136 additions & 0 deletions

File tree

buffer_rw.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,28 @@ func (buf *Buffer) PutByteAt(off int, b byte) {
100100
copyBits(buf.b, []byte{b}, buf.off+off, 0, 8)
101101
}
102102

103+
// RawBytes returns all the bits of the buffer as a byte slice. The caller must
104+
// not change the contents of the returned byte slice. The slice returned may or
105+
// may not reference to the internal buffer itself of buf, depending on whether
106+
// bit-shifting is needed of not. Also, if buf.Len() is not a multiple of 8, the
107+
// bits after the last bit in the slice returned are undefined. The main purpose
108+
// of RawBytes is to efficiently pass bit data to other byte-oriented APIs. In
109+
// general, it is recommended to use the safer Bytes() instead.
110+
func (buf *Buffer) RawBytes() []byte {
111+
if buf.off&7 == 0 {
112+
return buf.b[buf.off>>3 : (buf.off+buf.nBits+7)>>3]
113+
}
114+
return buf.Bytes()
115+
}
116+
117+
// Bytes returns all the bits of the buffer as a byte slice. If buf.Len() is not
118+
// a multiple of 8, it will be padded with 0.
119+
func (buf *Buffer) Bytes() []byte {
120+
b := make([]byte, (buf.nBits+7)>>3)
121+
copyBits(b, buf.b, 0, buf.off, buf.nBits)
122+
return b
123+
}
124+
103125
// BytesAt reads 8 * nBytes bits starting at the offset off and returns them as
104126
// a byte slice. Note that off is in bits, not bytes. If the off is not a
105127
// multiple of 8, it returns a properly shifted byte slice.

buffer_rw_example_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,32 @@ func ExampleBuffer_PutByteAt() {
9494
// 00111100000000
9595
}
9696

97+
func ExampleBuffer_RawBytes() {
98+
ba := bitarray.MustParse("1111-0000 1010-1010 1111-1111 11")
99+
buf := bitarray.NewBufferFromBitArray(ba)
100+
101+
// not byte-aligned, copied, 0-padded
102+
fmt.Printf("%08b\n", buf.Slice(3, 24).RawBytes())
103+
// byte-aligned, not copied, not 0-padded
104+
fmt.Printf("%08b\n", buf.Slice(3, 24).Slice(5, 16).RawBytes())
105+
106+
// Output:
107+
// [10000101 01010111 11111000]
108+
// [10101010 11111111]
109+
}
110+
111+
func ExampleBuffer_Bytes() {
112+
ba := bitarray.MustParse("1100-1010 1010-1111 0101-11")
113+
buf := bitarray.NewBufferFromBitArray(ba)
114+
115+
fmt.Printf("%08b\n", buf.Bytes())
116+
fmt.Printf("%08b\n", buf.Slice(4, 20).Bytes())
117+
118+
// Output:
119+
// [11001010 10101111 01011100]
120+
// [10101010 11110101]
121+
}
122+
97123
func ExampleBuffer_BytesAt() {
98124
ba := bitarray.MustParse("1100-1010 0011-1111 1010-0000 0111-1000")
99125
buf := bitarray.NewBufferFromBitArray(ba)

buffer_rw_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,94 @@ func TestBuffer_PutByteAt(t *testing.T) {
282282
chkpanic(0, 0)
283283
}
284284

285+
func TestBuffer_RawBytes(t *testing.T) {
286+
chk := func(buf *bitarray.Buffer, want ...byte) {
287+
t.Helper()
288+
got := buf.RawBytes()
289+
if !bytes.Equal(got, want) {
290+
t.Error("unexpected RawBytes():")
291+
t.Logf(" got: %08b", got)
292+
t.Logf("want: %08b", want)
293+
t.Logf(" buf: %s", buf.D())
294+
}
295+
}
296+
297+
ba := bitarray.MustParse("1100-1111 0000-1010 1100-1110 0011-01")
298+
buf := bitarray.NewBufferFromBitArray(ba)
299+
chk(
300+
buf,
301+
0b_1100_1111, 0b_0000_1010, 0b_1100_1110, 0b_0011_0100,
302+
)
303+
chk(
304+
buf.Slice(0, 17),
305+
0b_1100_1111, 0b_0000_1010, 0b_1100_1110,
306+
)
307+
chk(
308+
buf.Slice(4, 28),
309+
0b_1111_0000, 0b_1010_1100, 0b_1110_0011,
310+
)
311+
chk(
312+
buf.Slice(4, 24),
313+
0b_1111_0000, 0b_1010_1100, 0b_1110_0000,
314+
)
315+
chk(
316+
buf.Slice(4, 24).SliceToEnd(4),
317+
0b_0000_1010, 0b_1100_1110,
318+
)
319+
chk(
320+
buf.Slice(4, 24).Slice(4, 16),
321+
0b_0000_1010, 0b_1100_1110,
322+
)
323+
chk(
324+
buf.Slice(4, 24).SliceToEnd(6),
325+
0b_0010_1011, 0b_0011_1000,
326+
)
327+
}
328+
329+
func TestBuffer_Bytes(t *testing.T) {
330+
chk := func(buf *bitarray.Buffer, want ...byte) {
331+
t.Helper()
332+
got := buf.Bytes()
333+
if !bytes.Equal(got, want) {
334+
t.Error("unexpected Bytes():")
335+
t.Logf(" got: %08b", got)
336+
t.Logf("want: %08b", want)
337+
t.Logf(" buf: %s", buf.D())
338+
}
339+
}
340+
341+
ba := bitarray.MustParse("1100-1111 0000-1010 1100-1110 0011-01")
342+
buf := bitarray.NewBufferFromBitArray(ba)
343+
chk(
344+
buf,
345+
0b_1100_1111, 0b_0000_1010, 0b_1100_1110, 0b_0011_0100,
346+
)
347+
chk(
348+
buf.Slice(0, 17),
349+
0b_1100_1111, 0b_0000_1010, 0b_1000_0000,
350+
)
351+
chk(
352+
buf.Slice(4, 28),
353+
0b_1111_0000, 0b_1010_1100, 0b_1110_0011,
354+
)
355+
chk(
356+
buf.Slice(4, 24),
357+
0b_1111_0000, 0b_1010_1100, 0b_1110_0000,
358+
)
359+
chk(
360+
buf.Slice(4, 24).SliceToEnd(4),
361+
0b_0000_1010, 0b_1100_1110,
362+
)
363+
chk(
364+
buf.Slice(4, 24).Slice(4, 16),
365+
0b_0000_1010, 0b_1100_0000,
366+
)
367+
chk(
368+
buf.Slice(4, 24).SliceToEnd(6),
369+
0b_0010_1011, 0b_0011_1000,
370+
)
371+
}
372+
285373
func TestBuffer_BytesAt(t *testing.T) {
286374
buf := bitarray.NewBuffer(30)
287375
chk := func(off, nBytes int, want ...byte) {

0 commit comments

Comments
 (0)