-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprogress.go
87 lines (75 loc) · 1.8 KB
/
progress.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
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
package oget
import (
"io"
"sync/atomic"
)
type ProgressPhase int
const (
// ProgressPhaseDownloading is the phase of downloading.
ProgressPhaseDownloading ProgressPhase = iota
// ProgressPhaseCoping is the phase of merging from parts of temp files.
ProgressPhaseCoping
// ProgressPhaseDone is the phase of downloading done.
ProgressPhaseDone
)
// ProgressListener is the listener of the progress.
type ProgressListener func(event ProgressEvent)
// ProgressEvent is the event of the progress.
type ProgressEvent struct {
// the phase of the progress.
Phase ProgressPhase
// the progress of the downloading (bytes).
Progress int64
// the total length of the downloading (bytes).
Total int64
}
type progress struct {
phase ProgressPhase
length int64
progress int64
handler func(event ProgressEvent)
}
func downloadingProgress(length int64, handler func(event ProgressEvent)) *progress {
return &progress{
phase: ProgressPhaseDownloading,
length: length,
handler: handler,
progress: 0,
}
}
func (p *progress) toCopingPhase() *progress {
return &progress{
phase: ProgressPhaseCoping,
length: p.length,
handler: p.handler,
progress: 0,
}
}
func (p *progress) reader(proxy io.Reader) io.Reader {
return &progressReader{parent: p, proxy: proxy}
}
func (p *progress) fireDone() {
p.handler(ProgressEvent{
Phase: ProgressPhaseDone,
Total: p.length,
Progress: p.length,
})
}
type progressReader struct {
parent *progress
proxy io.Reader
}
func (r *progressReader) Read(p []byte) (int, error) {
n, err := r.proxy.Read(p)
if err != nil {
return n, err
}
parent := r.parent
progress := atomic.AddInt64(&parent.progress, int64(n))
r.parent.handler(ProgressEvent{
Phase: parent.phase,
Total: parent.length,
Progress: progress,
})
return n, err
}