-
Notifications
You must be signed in to change notification settings - Fork 0
/
tee_reader.go
59 lines (52 loc) · 1.3 KB
/
tee_reader.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
package tease
import (
"errors"
"io"
)
// TeeReader returns a Reader that writes to w what it reads from r.
// All reads from r performed through it are matched with
// corresponding writes to w. There is no internal buffering -
// the write must complete before the read completes.
// Any error encountered while writing is reported as a read error.
func TeeReadSeeker(r io.Reader, w io.Writer) *teeReadSeeker {
return &teeReadSeeker{
r: r,
w: w,
}
}
type teeReadSeeker struct {
r io.Reader
w io.Writer
pos int64
}
func (t *teeReadSeeker) Read(p []byte) (n int, err error) {
n, err = t.r.Read(p)
if n > 0 {
if n, err := t.w.Write(p[:n]); err != nil {
return n, err
}
}
return
}
func (mr *teeReadSeeker) Seek(offset int64, whence int) (int64, error) {
var abs int64
switch whence {
case io.SeekStart:
abs = offset
case io.SeekCurrent:
abs = mr.pos + offset
case io.SeekEnd:
return 0, errors.New("TeeReadSeeker.Seek: not implemented, seek from end")
default:
return 0, errors.New("TeeReadSeeker.Seek: invalid whence")
}
if abs < 0 {
return 0, errors.New("TeeReadSeeker.Seek: negative position")
}
if abs < mr.pos {
return 0, errors.New("TeeReadSeeker.Seek: cannot go backwards!")
}
np, err := io.CopyN(io.Discard, mr, abs-mr.pos)
mr.pos += int64(np)
return mr.pos, err
}