-
Notifications
You must be signed in to change notification settings - Fork 224
/
iobitreadseeker.go
106 lines (86 loc) · 2.38 KB
/
iobitreadseeker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package bitio
import (
"errors"
"io"
)
// IOBitReadSeeker is a bitio.ReadAtSeeker reading from a io.ReadSeeker.
type IOBitReadSeeker struct {
bitPos int64
rs io.ReadSeeker
buf []byte
}
// NewIOBitReadSeeker returns a new bitio.IOBitReadSeeker
func NewIOBitReadSeeker(rs io.ReadSeeker) *IOBitReadSeeker {
return &IOBitReadSeeker{
bitPos: 0,
rs: rs,
}
}
func (r *IOBitReadSeeker) ReadBitsAt(p []byte, nBits int64, bitOffset int64) (int64, error) {
if nBits < 0 {
return 0, ErrNegativeNBits
}
readBytePos := bitOffset / 8
readSkipBits := bitOffset % 8
wantReadBits := readSkipBits + nBits
wantReadBytes := int(BitsByteCount(wantReadBits))
if wantReadBytes > len(r.buf) {
// TODO: use append somehow?
r.buf = make([]byte, wantReadBytes)
}
_, err := r.rs.Seek(readBytePos, io.SeekStart)
if err != nil {
return 0, err
}
// TODO: nBits should be available
readBytes, err := io.ReadFull(r.rs, r.buf[0:wantReadBytes])
if err != nil && !errors.Is(err, io.ErrUnexpectedEOF) {
return 0, err
} else if errors.Is(err, io.ErrUnexpectedEOF) {
nBits = int64(readBytes) * 8
err = io.EOF
}
if readSkipBits == 0 && nBits%8 == 0 {
copy(p[0:readBytes], r.buf[0:readBytes])
return nBits, err
}
nBytes := nBits / 8
restBits := nBits % 8
// TODO: copy smartness if many bytes
for i := int64(0); i < nBytes; i++ {
p[i] = byte(Read64(r.buf, readSkipBits+i*8, 8))
}
if restBits != 0 {
p[nBytes] = byte(Read64(r.buf, readSkipBits+nBytes*8, restBits)) << (8 - restBits)
}
return nBits, err
}
func (r *IOBitReadSeeker) ReadBits(p []byte, nBits int64) (n int64, err error) {
rBits, err := r.ReadBitsAt(p, nBits, r.bitPos)
r.bitPos += rBits
return rBits, err
}
func (r *IOBitReadSeeker) SeekBits(bitOff int64, whence int) (int64, error) {
seekBytesPos, err := r.rs.Seek(bitOff/8, whence)
if err != nil {
return 0, err
}
seekBitPos := seekBytesPos*8 + bitOff%8
r.bitPos = seekBitPos
return seekBitPos, nil
}
func (r *IOBitReadSeeker) CloneReader() (Reader, error) {
return r.CloneReaderAtSeeker()
}
func (r *IOBitReadSeeker) CloneReadSeeker() (ReadSeeker, error) {
return r.CloneReaderAtSeeker()
}
func (r *IOBitReadSeeker) CloneReadAtSeeker() (ReadAtSeeker, error) {
return r.CloneReaderAtSeeker()
}
func (r *IOBitReadSeeker) CloneReaderAtSeeker() (ReaderAtSeeker, error) {
return NewIOBitReadSeeker(r.rs), nil
}
func (r *IOBitReadSeeker) Unwrap() any {
return r.rs
}