Commit 75199664 authored by Hector Chu's avatar Hector Chu Committed by Russ Cox

io: add TeeReader

TeeReader is a Reader that writes what it reads.

R=rsc, bradfitz
CC=golang-dev
https://golang.org/cl/4953041
parent bd3627cd
...@@ -437,3 +437,27 @@ func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err os.Error) { ...@@ -437,3 +437,27 @@ func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err os.Error) {
// Size returns the size of the section in bytes. // Size returns the size of the section in bytes.
func (s *SectionReader) Size() int64 { return s.limit - s.base } func (s *SectionReader) Size() int64 { return s.limit - s.base }
// 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 TeeReader(r Reader, w Writer) Reader {
return &teeReader{r, w}
}
type teeReader struct {
r Reader
w Writer
}
func (t *teeReader) Read(p []byte) (n int, err os.Error) {
n, err = t.r.Read(p)
if n > 0 {
if n, err := t.w.Write(p[:n]); err != nil {
return n, err
}
}
return
}
...@@ -177,3 +177,30 @@ func testReadAtLeast(t *testing.T, rb ReadWriter) { ...@@ -177,3 +177,30 @@ func testReadAtLeast(t *testing.T, rb ReadWriter) {
t.Errorf("expected to have read 1 bytes, got %v", n) t.Errorf("expected to have read 1 bytes, got %v", n)
} }
} }
func TestTeeReader(t *testing.T) {
src := []byte("hello, world")
dst := make([]byte, len(src))
rb := bytes.NewBuffer(src)
wb := new(bytes.Buffer)
r := TeeReader(rb, wb)
if n, err := ReadFull(r, dst); err != nil || n != len(src) {
t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src))
}
if !bytes.Equal(dst, src) {
t.Errorf("bytes read = %q want %q", dst, src)
}
if !bytes.Equal(wb.Bytes(), src) {
t.Errorf("bytes written = %q want %q", wb.Bytes(), src)
}
if n, err := r.Read(dst); n != 0 || err != os.EOF {
t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err)
}
rb = bytes.NewBuffer(src)
pr, pw := Pipe()
pr.Close()
r = TeeReader(rb, pw)
if n, err := ReadFull(r, dst); n != 0 || err != os.EPIPE {
t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment