This repository has been archived by the owner on Aug 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbyte.go
122 lines (105 loc) · 2.36 KB
/
byte.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package unit
import (
"fmt"
"math"
"strconv"
"strings"
"github.com/deixis/errors"
)
// Byte represents a byte size
type Byte float64
const (
_ = iota
// KB means kilobyte
KB Byte = 1 << (10 * iota)
// MB means megabyte
MB
// GB means gigabyte
GB
// TB means terabyte
TB
)
// ParseByte parses the string and return a Byte struct
//
// e.g. 3.3 kB, 3kB, 7 GB, 9 TB, -1 TB
func ParseByte(s string) (Byte, error) {
s = strings.TrimSpace(s)
if len(s) < 3 {
return 0, fmt.Errorf("invalid format")
}
// Either we have a space in between (or not)
res := strings.Split(s, " ")
var n, scale string
if len(res) == 2 {
n = res[0]
scale = res[1]
} else {
n = s[0 : len(s)-2]
scale = s[len(s)-2:]
}
var mag Byte
switch scale {
case "B":
mag = 1
case "kB":
mag = KB
case "MB":
mag = MB
case "GB":
mag = GB
case "TB":
mag = TB
default:
return 0, fmt.Errorf("unknown scale %s", scale)
}
v, err := strconv.ParseFloat(n, 64)
if err != nil {
return 0, errors.Wrap(err, "invalid number")
}
return Byte(v) * mag, nil
}
func (b Byte) String() string {
switch {
case math.Abs(float64(b/TB)) >= 1:
return strconv.FormatFloat(float64(b/TB), 'f', -1, 64) + " TB"
case math.Abs(float64(b/GB)) >= 1:
return strconv.FormatFloat(float64(b/GB), 'f', -1, 64) + " GB"
case math.Abs(float64(b/MB)) >= 1:
return strconv.FormatFloat(float64(b/MB), 'f', -1, 64) + " MB"
case math.Abs(float64(b/KB)) >= 1:
return strconv.FormatFloat(float64(b/KB), 'f', -1, 64) + " kB"
}
return strconv.FormatFloat(float64(b), 'f', -1, 64) + " B"
}
// Gt returns whether the value b is greater than v
func (b Byte) Gt(v int64) bool {
return b > Byte(v)
}
// Lt returns whether the value b is less than v
func (b Byte) Lt(v int64) bool {
return b < Byte(v)
}
// MarshalJSON implements the json.Marshaler interface.
func (b Byte) MarshalJSON() ([]byte, error) {
return []byte(strings.Join([]string{"\"", b.String(), "\""}, "")), nil
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (b *Byte) UnmarshalJSON(data []byte) error {
r, err := ParseByte(strings.Trim(string(data), "\""))
if err != nil {
return err
}
*b = r
return nil
}
func (b Byte) MarshalText() (text []byte, err error) {
return []byte(b.String()), nil
}
func (b *Byte) UnmarshalText(text []byte) error {
r, err := ParseByte(string(text))
if err != nil {
return err
}
*b = r
return nil
}