-
Notifications
You must be signed in to change notification settings - Fork 46
/
helpers.go
103 lines (89 loc) · 2.72 KB
/
helpers.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
package common
import (
"fmt"
"io"
"regexp"
"runtime"
"sort"
"strconv"
"strings"
)
var RuntimeGOARCH = runtime.GOARCH
func CurrentArch() string {
if RuntimeGOARCH == "amd64" {
return "x86_64"
} else if RuntimeGOARCH == "arm64" {
return "aarch64"
} else if RuntimeGOARCH == "ppc64le" {
return "ppc64le"
} else if RuntimeGOARCH == "s390x" {
return "s390x"
} else {
panic("unsupported architecture")
}
}
func PanicOnError(err error) {
if err != nil {
panic(err)
}
}
// IsStringInSortedSlice returns true if the string is present, false if not
// slice must be sorted
func IsStringInSortedSlice(slice []string, s string) bool {
i := sort.SearchStrings(slice, s)
if i < len(slice) && slice[i] == s {
return true
}
return false
}
// DataSizeToUint64 converts a size specified as a string in KB/KiB/MB/etc. to
// a number of bytes represented by uint64.
func DataSizeToUint64(size string) (uint64, error) {
// Pre-process the input
size = strings.TrimSpace(size)
// Get the number from the string
plain_number := regexp.MustCompile(`[[:digit:]]+`)
number_as_str := plain_number.FindString(size)
if number_as_str == "" {
return 0, fmt.Errorf("the size string doesn't contain any number: %s", size)
}
// Parse the number into integer
return_size, err := strconv.ParseUint(number_as_str, 10, 64)
if err != nil {
return 0, fmt.Errorf("failed to parse size as integer: %s", number_as_str)
}
// List of all supported units (from kB to TB and KiB to TiB)
supported_units := []struct {
re *regexp.Regexp
multiple uint64
}{
{regexp.MustCompile(`^\s*[[:digit:]]+\s*kB$`), KiloByte},
{regexp.MustCompile(`^\s*[[:digit:]]+\s*KiB$`), KibiByte},
{regexp.MustCompile(`^\s*[[:digit:]]+\s*MB$`), MegaByte},
{regexp.MustCompile(`^\s*[[:digit:]]+\s*MiB$`), MebiByte},
{regexp.MustCompile(`^\s*[[:digit:]]+\s*GB$`), GigaByte},
{regexp.MustCompile(`^\s*[[:digit:]]+\s*GiB$`), GibiByte},
{regexp.MustCompile(`^\s*[[:digit:]]+\s*TB$`), TeraByte},
{regexp.MustCompile(`^\s*[[:digit:]]+\s*TiB$`), TebiByte},
{regexp.MustCompile(`^\s*[[:digit:]]+$`), 1},
}
for _, unit := range supported_units {
if unit.re.MatchString(size) {
return_size *= unit.multiple
return return_size, nil
}
}
// In case the strign didn't match any of the above regexes, return nil
// even if a number was found. This is to prevent users from submitting
// unknown units.
return 0, fmt.Errorf("unknown data size units in string: %s", size)
}
// NopSeekCloser returns an io.ReadSeekCloser with a no-op Close method
// wrapping the provided io.ReadSeeker r.
func NopSeekCloser(r io.ReadSeeker) io.ReadSeekCloser {
return nopSeekCloser{r}
}
type nopSeekCloser struct {
io.ReadSeeker
}
func (nopSeekCloser) Close() error { return nil }