Hunter0x7c7
2022-08-11 a82f9cb69f63aaeba40c024960deda7d75b9fece
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
94
95
96
97
98
99
100
package units
 
import (
    "errors"
    "strconv"
    "strings"
    "unicode"
)
 
var (
    errInvalidSize = errors.New("invalid size")
    errInvalidUnit = errors.New("invalid or unsupported unit")
)
 
// ByteSize is the size of bytes
type ByteSize uint64
 
const (
    _ = iota
    // KB = 1KB
    KB ByteSize = 1 << (10 * iota)
    // MB = 1MB
    MB
    // GB = 1GB
    GB
    // TB = 1TB
    TB
    // PB = 1PB
    PB
    // EB = 1EB
    EB
)
 
func (b ByteSize) String() string {
    unit := ""
    value := float64(0)
    switch {
    case b == 0:
        return "0"
    case b < KB:
        unit = "B"
        value = float64(b)
    case b < MB:
        unit = "KB"
        value = float64(b) / float64(KB)
    case b < GB:
        unit = "MB"
        value = float64(b) / float64(MB)
    case b < TB:
        unit = "GB"
        value = float64(b) / float64(GB)
    case b < PB:
        unit = "TB"
        value = float64(b) / float64(TB)
    case b < EB:
        unit = "PB"
        value = float64(b) / float64(PB)
    default:
        unit = "EB"
        value = float64(b) / float64(EB)
    }
    result := strconv.FormatFloat(value, 'f', 2, 64)
    result = strings.TrimSuffix(result, ".0")
    return result + unit
}
 
// Parse parses ByteSize from string
func (b *ByteSize) Parse(s string) error {
    s = strings.TrimSpace(s)
    s = strings.ToUpper(s)
    i := strings.IndexFunc(s, unicode.IsLetter)
    if i == -1 {
        return errInvalidUnit
    }
 
    bytesString, multiple := s[:i], s[i:]
    bytes, err := strconv.ParseFloat(bytesString, 64)
    if err != nil || bytes <= 0 {
        return errInvalidSize
    }
    switch multiple {
    case "B":
        *b = ByteSize(bytes)
    case "K", "KB", "KIB":
        *b = ByteSize(bytes * float64(KB))
    case "M", "MB", "MIB":
        *b = ByteSize(bytes * float64(MB))
    case "G", "GB", "GIB":
        *b = ByteSize(bytes * float64(GB))
    case "T", "TB", "TIB":
        *b = ByteSize(bytes * float64(TB))
    case "P", "PB", "PIB":
        *b = ByteSize(bytes * float64(PB))
    case "E", "EB", "EIB":
        *b = ByteSize(bytes * float64(EB))
    default:
        return errInvalidUnit
    }
    return nil
}