Skip to content

Commit 50a44ed

Browse files
committed
#114 add proxy reader
1 parent 4a1bf7a commit 50a44ed

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

pb.go

+10
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ func (pb *ProgressBar) Add(value int) *ProgressBar {
242242
return pb.Add64(int64(value))
243243
}
244244

245+
// Increment atomically increments the progress
245246
func (pb *ProgressBar) Increment() *ProgressBar {
246247
return pb.Add64(1)
247248
}
@@ -360,6 +361,7 @@ func (pb *ProgressBar) Finish() *ProgressBar {
360361
return pb
361362
}
362363

364+
// IsStarted indicates progress bar state
363365
func (pb *ProgressBar) IsStarted() bool {
364366
pb.mu.RLock()
365367
defer pb.mu.RUnlock()
@@ -379,6 +381,14 @@ func (pb *ProgressBar) SetTemplate(tmpl ProgressBarTemplate) *ProgressBar {
379381
return pb.SetTemplateString(string(tmpl))
380382
}
381383

384+
// NewProxyReader creates a wrapper for given reader, but with progress handle
385+
// Takes io.Reader or io.ReadCloser
386+
// Also, it automatically switches progress bar to handle units as bytes
387+
func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader {
388+
pb.Set(Bytes, true)
389+
return &Reader{r, pb}
390+
}
391+
382392
func (pb *ProgressBar) render() (result string, width int) {
383393
defer func() {
384394
if r := recover(); r != nil {

reader.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package pb
2+
3+
import (
4+
"io"
5+
)
6+
7+
// Reader it's a wrapper for given reader, but with progress handle
8+
type Reader struct {
9+
io.Reader
10+
bar *ProgressBar
11+
}
12+
13+
// Read reads bytes from wrapped reader and add amount of bytes to progress bar
14+
func (r *Reader) Read(p []byte) (n int, err error) {
15+
n, err = r.Reader.Read(p)
16+
r.bar.Add(n)
17+
return
18+
}
19+
20+
// Close the wrapped reader when it implements io.Closer
21+
func (r *Reader) Close() (err error) {
22+
if closer, ok := r.Reader.(io.Closer); ok {
23+
return closer.Close()
24+
}
25+
return
26+
}

reader_test.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package pb
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestPBProxyReader(t *testing.T) {
8+
bar := new(ProgressBar)
9+
if bar.GetBool(Bytes) {
10+
t.Errorf("By default bytes must be false")
11+
}
12+
13+
testReader := new(testReaderCloser)
14+
proxyReader := bar.NewProxyReader(testReader)
15+
16+
if !bar.GetBool(Bytes) {
17+
t.Errorf("Bytes must be true after call NewProxyReader")
18+
}
19+
20+
for i := 0; i < 10; i++ {
21+
buf := make([]byte, 10)
22+
n, e := proxyReader.Read(buf)
23+
if e != nil {
24+
t.Errorf("Proxy reader return err: %v", e)
25+
}
26+
if n != len(buf) {
27+
t.Errorf("Proxy reader return unexpected N: %d (wand %d)", n, len(buf))
28+
}
29+
for _, b := range buf {
30+
if b != 'f' {
31+
t.Errorf("Unexpected read value: %v (want %v)", b, 'f')
32+
}
33+
}
34+
if want := int64((i + 1) * len(buf)); bar.Current() != want {
35+
t.Errorf("Unexpected bar current value: %d (want %d)", bar.Current(), want)
36+
}
37+
}
38+
proxyReader.Close()
39+
if !testReader.closed {
40+
t.Errorf("Reader must be closed after call ProxyReader.Close")
41+
}
42+
}
43+
44+
type testReaderCloser struct {
45+
closed bool
46+
}
47+
48+
func (tr *testReaderCloser) Read(p []byte) (n int, err error) {
49+
for i := range p {
50+
p[i] = 'f'
51+
}
52+
return len(p), nil
53+
}
54+
55+
func (tr *testReaderCloser) Close() (err error) {
56+
tr.closed = true
57+
return
58+
}

0 commit comments

Comments
 (0)