-
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathsection_read_seeker.go
75 lines (68 loc) · 1.42 KB
/
section_read_seeker.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
package missinggo
import (
"context"
"fmt"
"io"
)
type sectionReadSeeker struct {
base io.ReadSeeker
off, size int64
}
type ReadSeekContexter interface {
io.ReadSeeker
ReadContexter
}
// Returns a ReadSeeker on a section of another ReadSeeker.
func NewSectionReadSeeker(base io.ReadSeeker, off, size int64) (ret ReadSeekContexter) {
ret = §ionReadSeeker{
base: base,
off: off,
size: size,
}
seekOff, err := ret.Seek(0, io.SeekStart)
if err != nil {
panic(err)
}
if seekOff != 0 {
panic(seekOff)
}
return
}
func (me *sectionReadSeeker) Seek(off int64, whence int) (ret int64, err error) {
switch whence {
case io.SeekStart:
off += me.off
case io.SeekCurrent:
case io.SeekEnd:
off += me.off + me.size
whence = io.SeekStart
default:
err = fmt.Errorf("unhandled whence: %d", whence)
return
}
ret, err = me.base.Seek(off, whence)
ret -= me.off
return
}
func (me *sectionReadSeeker) ReadContext(ctx context.Context, b []byte) (int, error) {
off, err := me.Seek(0, io.SeekCurrent)
if err != nil {
return 0, err
}
left := me.size - off
if left <= 0 {
return 0, io.EOF
}
b = LimitLen(b, left)
if rc, ok := me.base.(ReadContexter); ok {
return rc.ReadContext(ctx, b)
}
if ctx != context.Background() {
// Can't handle cancellation.
panic(ctx)
}
return me.base.Read(b)
}
func (me *sectionReadSeeker) Read(b []byte) (int, error) {
return me.ReadContext(context.Background(), b)
}