-
Notifications
You must be signed in to change notification settings - Fork 0
/
reader.go
52 lines (46 loc) · 1.3 KB
/
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
// Streamy
// For the full copyright and license information, please view the LICENSE.txt file.
package streamy
import (
"io"
)
// TeeReaderN returns an io.Reader that writes to the given writer what it reads from the given reader.
// It's similar to io.TeeReader but takes an additional argument that controls the number of bytes to write.
func TeeReaderN(r io.Reader, w io.Writer, n int64) io.Reader {
return &teeReaderN{r: r, w: w, limit: n}
}
// teeReaderN represents a TeeReaderN entity.
type teeReaderN struct {
r io.Reader
w io.Writer
limit int64
written int64
}
// Read implements the io.Reader interface.
func (t *teeReaderN) Read(p []byte) (n int, err error) {
read, err := t.r.Read(p)
if read > 0 && t.limit > t.written {
high := int64(read)
if (t.written + high) > t.limit {
high = t.limit - t.written
}
written, err := t.w.Write(p[:high])
if err != nil {
return read, err
}
t.written += int64(written)
}
return read, err
}
// ReaderOnly takes any interface that implements io.Reader and returns just an io.Reader.
// It's useful for converting "advanced" readers (i.e. io.Seeker) to streams.
func ReaderOnly(r io.Reader) io.Reader {
pr, pw := io.Pipe()
go func() {
defer pw.Close()
if _, err := io.Copy(pw, r); err != nil {
panic(err)
}
}()
return pr
}