/* Reader implementation. */ package bitio import ( "bufio" "io" ) // An io.Reader and io.ByteReader at the same time. type readerAndByteReader interface { io.Reader io.ByteReader } // Reader is the bit reader implementation. // // For convenience, it also implements io.Reader and io.ByteReader. type Reader struct { in readerAndByteReader cache byte // unread bits are stored here bits byte // number of unread bits in cache // TryError holds the first error occurred in TryXXX() methods. TryError error } // NewReader returns a new Reader using the specified io.Reader as the input (source). func NewReader(in io.Reader) *Reader { bin, ok := in.(readerAndByteReader) if !ok { bin = bufio.NewReader(in) } return &Reader{in: bin} } // Read reads up to len(p) bytes (8 * len(p) bits) from the underlying reader. // // Read implements io.Reader, and gives a byte-level view of the bit stream. // This will give best performance if the underlying io.Reader is aligned // to a byte boundary (else all the individual bytes are assembled from multiple bytes). // Byte boundary can be ensured by calling Align(). func (r *Reader) Read(p []byte) (n int, err error) { // r.bits will be the same after reading 8 bits, so we don't need to update that. if r.bits == 0 { return r.in.Read(p) } for ; n < len(p); n++ { if p[n], err = r.readUnalignedByte(); err != nil { return } } return } // ReadBits reads n bits and returns them as the lowest n bits of u. func (r *Reader) ReadBits(n uint8) (u uint64, err error) { // Some optimization, frequent cases if n < r.bits { // cache has all needed bits, and there are some extra which will be left in cache shift := r.bits - n u = uint64(r.cache >> shift) r.cache &= 1< r.bits { // all cache bits needed, and it's not even enough so more will be read if r.bits > 0 { u = uint64(r.cache) n -= r.bits } // Read whole bytes for n >= 8 { b, err2 := r.in.ReadByte() if err2 != nil { return 0, err2 } u = u<<8 + uint64(b) n -= 8 } // Read last fraction, if any if n > 0 { if r.cache, err = r.in.ReadByte(); err != nil { return 0, err } shift := 8 - n u = u<>shift) r.cache &= 1<> bits r.cache &= 1<