| 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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
 | package rifs
import (
	"io"
	"time"
	"github.com/dsoprea/go-logging"
)
// ProgressFunc receives progress updates.
type ProgressFunc func(n int, duration time.Duration, isEof bool) error
// WriteProgressWrapper wraps a reader and calls a callback after each read with
// count and duration info.
type WriteProgressWrapper struct {
	w          io.Writer
	progressCb ProgressFunc
}
// NewWriteProgressWrapper returns a new WPW instance.
func NewWriteProgressWrapper(w io.Writer, progressCb ProgressFunc) io.Writer {
	return &WriteProgressWrapper{
		w:          w,
		progressCb: progressCb,
	}
}
// Write does a write and calls the callback.
func (wpw *WriteProgressWrapper) Write(buffer []byte) (n int, err error) {
	defer func() {
		if state := recover(); state != nil {
			err = log.Wrap(state.(error))
		}
	}()
	startAt := time.Now()
	n, err = wpw.w.Write(buffer)
	log.PanicIf(err)
	duration := time.Since(startAt)
	err = wpw.progressCb(n, duration, false)
	log.PanicIf(err)
	return n, nil
}
// ReadProgressWrapper wraps a reader and calls a callback after each read with
// count and duration info.
type ReadProgressWrapper struct {
	r          io.Reader
	progressCb ProgressFunc
}
// NewReadProgressWrapper returns a new RPW instance.
func NewReadProgressWrapper(r io.Reader, progressCb ProgressFunc) io.Reader {
	return &ReadProgressWrapper{
		r:          r,
		progressCb: progressCb,
	}
}
// Read reads data and calls the callback.
func (rpw *ReadProgressWrapper) Read(buffer []byte) (n int, err error) {
	defer func() {
		if state := recover(); state != nil {
			err = log.Wrap(state.(error))
		}
	}()
	startAt := time.Now()
	n, err = rpw.r.Read(buffer)
	duration := time.Since(startAt)
	if err != nil {
		if err == io.EOF {
			errInner := rpw.progressCb(n, duration, true)
			log.PanicIf(errInner)
			return n, err
		}
		log.Panic(err)
	}
	err = rpw.progressCb(n, duration, false)
	log.PanicIf(err)
	return n, nil
}
 |