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
|
package meter
import (
"fmt"
"io"
"math"
"time"
)
func FormatByteRate(b uint64, d time.Duration) string {
b = uint64(float64(b) / math.Max(time.Nanosecond.Seconds(), d.Seconds()))
rate, prefix := formatBytes(b)
if prefix == 0 {
return fmt.Sprintf("%d B/s", int(rate))
}
return fmt.Sprintf("%.1f %cB/s", rate, prefix)
}
func FormatBytes(b uint64) string {
size, prefix := formatBytes(b)
if prefix == 0 {
return fmt.Sprintf("%d B", int(size))
}
return fmt.Sprintf("%.2f %cB", size, prefix)
}
func formatBytes(b uint64) (float64, byte) {
const (
unit = 1000
prefix = "KMGTPE"
)
if b < unit {
return float64(b), 0
}
div := int64(unit)
exp := 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return float64(b) / float64(div), prefix[exp]
}
func LabelledRateFormat(w io.Writer, label string, totalSize int64) UpdateCallback {
return func(written uint64, since time.Duration, done bool) {
known := ""
if totalSize > UnknownTotalSize {
known = "/" + FormatBytes(uint64(totalSize))
}
line := fmt.Sprintf(
"\r%s %s%s (%s) ",
label,
FormatBytes(written),
known,
FormatByteRate(written, since),
)
if done {
_, _ = fmt.Fprintln(w, line)
return
}
_, _ = fmt.Fprint(w, line)
}
}
|