github.com/tunabay/go-bitarray@v1.3.1/reader.go (about) 1 // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved. 2 // Use of this source code is governed by the MIT license that can be found in 3 // the LICENSE file. 4 5 package bitarray 6 7 import ( 8 "io" 9 ) 10 11 // Reader implements io.Reader and io.ByteReader interfaces by reading from a 12 // BitArray. 13 // 14 // The standard io.Reader family interfaces define byte-oriented reading 15 // methods, rather than bit-oriented. And they always read in bytes and cannot 16 // read fractional bits less than 8 bits. When the number of remaining available 17 // bits is not a multiple of 8, the io.EOF may be reached with fractional bits 18 // remaining. In this case, the padding bits are not added automatically and an 19 // ErrFractionalBitsBeforeEOF is returned. To handle these trailing fractional 20 // bits, use bit-oriented reads together, or use ToPadded8 etc in advance to 21 // make sure that the number of bits in the source is a multiple of 8 bits. 22 type Reader struct { 23 ba *BitArray 24 i int 25 } 26 27 // NewReader returns a new Reader reading from the bit array ba. For mutable 28 // types of ba, the value at the time NewReader is called is copied and 29 // subsequent changes will not be reflected in future readings. 30 func NewReader(ba BitArrayer) *Reader { 31 if ba == nil { 32 return &Reader{ba: zeroBitArray} 33 } 34 35 return &Reader{ba: ba.BitArray()} 36 } 37 38 // Reset resets the Reader to be reading from ba. 39 func (r *Reader) Reset(ba BitArrayer) { 40 if ba == nil { 41 r.ba = zeroBitArray 42 } else { 43 r.ba = ba.BitArray() 44 } 45 r.i = 0 46 } 47 48 // Read implements the io.Reader interface. It reads up to 8 * len(p) bits from 49 // the underlying BitArray, writes them to p as bytes, and returns the number of 50 // bytes read. It always reads in bytes, and if only fractional bits less than 8 51 // bits are available, it returns an ErrFractionalBitsBeforeEOF. 52 func (r *Reader) Read(p []byte) (int, error) { 53 switch { 54 case r.ba.IsZero(), r.ba.nBits <= r.i: 55 return 0, io.EOF 56 case r.ba.nBits-8 < r.i: 57 return 0, ErrFractionalBitsBeforeEOF 58 } 59 nBytes := len(p) 60 if n := (r.ba.Len() - r.i) >> 3; n < nBytes { 61 nBytes = n 62 } 63 switch { 64 case nBytes == 0: 65 return 0, nil 66 case r.ba.b == nil: 67 fill00(p[:nBytes]) 68 r.i += nBytes << 3 69 return nBytes, nil 70 } 71 _ = copyBits(p[:nBytes], r.ba.b, 0, r.i, nBytes<<3) 72 r.i += nBytes << 3 73 return nBytes, nil 74 } 75 76 // ReadByte implements the io.ByteReader interface. It reads 8 bits from the 77 // underlying BitArray and returns them as a byte. If only fractional bits less 78 // than 8 bits are available, it returns an ErrFractionalBitsBeforeEOF. 79 func (r *Reader) ReadByte() (byte, error) { 80 switch { 81 case r.ba.IsZero(), r.ba.nBits <= r.i: 82 return 0, io.EOF 83 case r.ba.nBits-8 < r.i: 84 return 0, ErrFractionalBitsBeforeEOF 85 } 86 if r.ba.b == nil { 87 r.i += 8 88 return 0, nil 89 } 90 b := make([]byte, 1) 91 _ = copyBits(b, r.ba.b, 0, r.i, 8) 92 r.i += 8 93 return b[0], nil 94 } 95 96 // ReadBitArray reads up to nBits bits as a BitArray. The returned BitArray may 97 // be shorter than nBits. The caller should check the length of the returned 98 // bit array and handle it. 99 func (r *Reader) ReadBitArray(nBits int) (*BitArray, error) { 100 switch { 101 case nBits < 0: 102 panicf("ReadBitArray: negative nBits %d.", nBits) 103 case nBits == 0: 104 return zeroBitArray, nil 105 case r.ba.IsZero(), r.ba.nBits <= r.i: 106 return zeroBitArray, io.EOF 107 } 108 if n := r.ba.nBits - r.i; n < nBits { 109 nBits = n 110 } 111 ba := r.ba.Slice(r.i, r.i+nBits) 112 r.i += nBits 113 114 return ba, nil 115 } 116 117 // ReadBit reads a single bit as 0 or 1. 118 func (r *Reader) ReadBit() (byte, error) { 119 if r.ba.IsZero() || r.ba.nBits <= r.i { 120 return 0, io.EOF 121 } 122 if r.ba.b == nil { 123 r.i++ 124 return 0, nil 125 } 126 b := r.ba.b[r.i>>3] >> (7 - r.i&7) & 1 127 r.i++ 128 return b, nil 129 } 130 131 // ReadBits reads up to p.Len() bits into p. It returns the number of bits read 132 // (0 <= n <= p.Len()) and any error encountered. The data in the buffer beyond 133 // the returned length is undefined. 134 func (r *Reader) ReadBits(p *Buffer) (int, error) { 135 nBits := p.Len() 136 switch { 137 case nBits == 0: 138 return 0, nil 139 case r.ba.IsZero(), r.ba.nBits <= r.i: 140 return 0, io.EOF 141 } 142 if n := r.ba.nBits - r.i; n < nBits { 143 nBits = n 144 } 145 if r.ba.b == nil { 146 clearBits(p.b, 0, nBits) 147 } else { 148 _ = copyBits(p.b, r.ba.b, 0, r.i, nBits) 149 } 150 r.i += nBits 151 152 return nBits, nil 153 } 154 155 /* 156 // TODO: 157 // WriteTo implements the io.WriterTo interface. 158 func (r *Reader) WriteTo(w io.Writer) (int64, error) {} 159 */