5 // ProgressEventType defines transfer progress event type
6 type ProgressEventType int
9 // TransferStartedEvent transfer started, set TotalBytes
10 TransferStartedEvent ProgressEventType = 1 + iota
11 // TransferDataEvent transfer data, set ConsumedBytes anmd TotalBytes
13 // TransferCompletedEvent transfer completed
14 TransferCompletedEvent
15 // TransferFailedEvent transfer encounters an error
19 // ProgressEvent defines progress event
20 type ProgressEvent struct {
24 EventType ProgressEventType
27 // ProgressListener listens progress change
28 type ProgressListener interface {
29 ProgressChanged(event *ProgressEvent)
32 // -------------------- Private --------------------
34 func newProgressEvent(eventType ProgressEventType, consumed, total int64, rwBytes int64) *ProgressEvent {
35 return &ProgressEvent{
36 ConsumedBytes: consumed,
43 func publishProgress(listener ProgressListener, event *ProgressEvent) {
44 if listener != nil && event != nil {
45 listener.ProgressChanged(event)
49 type readerTracker struct {
53 type teeReader struct {
56 listener ProgressListener
59 tracker *readerTracker
62 // TeeReader returns a Reader that writes to w what it reads from r.
63 // All reads from r performed through it are matched with
64 // corresponding writes to w. There is no internal buffering -
65 // the write must complete before the read completes.
66 // Any error encountered while writing is reported as a read error.
67 func TeeReader(reader io.Reader, writer io.Writer, totalBytes int64, listener ProgressListener, tracker *readerTracker) io.ReadCloser {
73 totalBytes: totalBytes,
78 func (t *teeReader) Read(p []byte) (n int, err error) {
79 n, err = t.reader.Read(p)
81 // Read encountered error
82 if err != nil && err != io.EOF {
83 event := newProgressEvent(TransferFailedEvent, t.consumedBytes, t.totalBytes, 0)
84 publishProgress(t.listener, event)
88 t.consumedBytes += int64(n)
91 if n, err := t.writer.Write(p[:n]); err != nil {
96 if t.listener != nil {
97 event := newProgressEvent(TransferDataEvent, t.consumedBytes, t.totalBytes, int64(n))
98 publishProgress(t.listener, event)
101 if t.tracker != nil {
102 t.tracker.completedBytes = t.consumedBytes
109 func (t *teeReader) Close() error {
110 if rc, ok := t.reader.(io.ReadCloser); ok {