Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Add comment about error catching.
package main
import (
"io"
"bytes"
"fmt"
)
type PlainBitReader struct {
reader io.ByteReader
byte byte
offset uint8
}
// Simple new method to return new instance
func NewPlainBitReader(reader io.ByteReader) *PlainBitReader {
return &PlainBitReader{reader, 0, 0}
}
// We may encounter a read error from our reader.
// If so, we'll return that and the returned bit is considered invalid.
func (bitReader *PlainBitReader) ReadBit() (bool, error) {
if (bitReader.offset == 8) { bitReader.offset = 0 }
// Get next byte
if (bitReader.offset == 0) {
var err error
bitReader.byte, err = bitReader.reader.ReadByte()
if (err != nil) {
return false, err
}
}
// Compare current byte to 10000000 shifted right bitReader.offset times
bit := bitReader.byte & (0x80 >> bitReader.offset)
// Increment our offset
bitReader.offset++
// Comparison will turn byte to boolean, and no error is returned
return bit != 0, nil
}
// We may encounter errors again, so we'll perform the same behavior as last time.
func (bitReader *PlainBitReader) ReadBits(bits int64) (uint64, error) {
var bitRange uint64
// Read from bits - 1 to 0
for i := bits - 1; i >= 0; i-- {
bit, err := bitReader.ReadBit()
if (err != nil) { return uint64(0), err }
if (bit) {
// xxxxxxxxx
// 1 << bits - 1 - amount of iterations
// Compared via OR.
// We're altering each individual bit of our uint64 each iteration, essentially.
bitRange |= (1 << uint64(i))
}
}
return bitRange, nil
}
func main() {
// Bytes:
// 11111111 == 256
// 00000000 == 0
// 00001111 == 15
bits := []byte { 0xFF, 0x00, 0x0F }
bitReader := NewPlainBitReader(bytes.NewBuffer(bits))
// Read first 6 bits of our byte buffer.
// Bits: 111111 (== 63)
uintValue, err := bitReader.ReadBits(6)
// Error catching
// For brevity, I omitted the rest of these
if (err != nil) { panic(err) }
fmt.Println(uintValue)
// Read next 10 bits.
// Bits: 1100000000 (== 768)
uintValue, _ = bitReader.ReadBits(10)
fmt.Println(uintValue)
// Read next 4 bits.
// Bits: 0000 (== 0, obviously)
uintValue, _ = bitReader.ReadBits(4)
fmt.Println(uintValue)
// Read last 4 bits.
// Bits: 1111 (== 15)
uintValue, _ = bitReader.ReadBits(4)
fmt.Println(uintValue)
// Output:
// 63
// 768
// 0
// 15
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment