read.go (1751B)
1 package bitio 2 3 import "io" 4 5 type Reader interface { 6 io.Reader 7 8 // alignment: 9 // |-1-byte-block-|--------------|--------------|--------------| 10 // |<-offset->|<-------------------width---------------------->| 11 ReadBits(width uint) (data []byte, err error) 12 13 ReadBit() (bit bool, err error) 14 } 15 16 type ReadSeeker interface { 17 Reader 18 io.Seeker 19 } 20 21 type reader struct { 22 reader io.Reader 23 octet byte 24 width uint 25 } 26 27 func NewReader(r io.Reader) Reader { 28 return &reader{reader: r} 29 } 30 31 func (r *reader) Read(p []byte) (n int, err error) { 32 if r.width != 0 { 33 return 0, ErrInvalidAlignment 34 } 35 return r.reader.Read(p) 36 } 37 38 func (r *reader) ReadBits(size uint) ([]byte, error) { 39 bytes := (size + 7) / 8 40 data := make([]byte, bytes) 41 offset := (bytes * 8) - (size) 42 43 for i := uint(0); i < size; i++ { 44 bit, err := r.ReadBit() 45 if err != nil { 46 return nil, err 47 } 48 49 byteIdx := (offset + i) / 8 50 bitIdx := 7 - (offset+i)%8 51 if bit { 52 data[byteIdx] |= 0x1 << bitIdx 53 } 54 } 55 56 return data, nil 57 } 58 59 func (r *reader) ReadBit() (bool, error) { 60 if r.width == 0 { 61 buf := make([]byte, 1) 62 if n, err := r.reader.Read(buf); err != nil { 63 return false, err 64 } else if n != 1 { 65 return false, ErrDiscouragedReader 66 } 67 r.octet = buf[0] 68 r.width = 8 69 } 70 71 r.width-- 72 return (r.octet>>r.width)&0x01 != 0, nil 73 } 74 75 type readSeeker struct { 76 reader 77 seeker io.Seeker 78 } 79 80 func NewReadSeeker(r io.ReadSeeker) ReadSeeker { 81 return &readSeeker{ 82 reader: reader{reader: r}, 83 seeker: r, 84 } 85 } 86 87 func (r *readSeeker) Seek(offset int64, whence int) (int64, error) { 88 if whence == io.SeekCurrent && r.reader.width != 0 { 89 return 0, ErrInvalidAlignment 90 } 91 n, err := r.seeker.Seek(offset, whence) 92 if err != nil { 93 return n, err 94 } 95 r.reader.width = 0 96 return n, nil 97 }