Skip to content

Commit bdef54d

Browse files
mvo5achilleas-k
authored andcommitted
pkg: add new datasizes package that adds constants and parsing
This commit extracts the existing `common.DataSizeToUint64` and the `common.{Ki,Gi,Mi,...}` and similar data size constants into a new package `datasizes` that will be shared with other packages like `blueprints`.
1 parent 7b89d25 commit bdef54d

File tree

6 files changed

+123
-107
lines changed

6 files changed

+123
-107
lines changed

Diff for: internal/common/constants.go

-19
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,6 @@ package common
22

33
import "fmt"
44

5-
const (
6-
KiloByte = 1000 // kB
7-
KibiByte = 1024 // KiB
8-
MegaByte = 1000 * 1000 // MB
9-
MebiByte = 1024 * 1024 // MiB
10-
GigaByte = 1000 * 1000 * 1000 // GB
11-
GibiByte = 1024 * 1024 * 1024 // GiB
12-
TeraByte = 1000 * 1000 * 1000 * 1000 // TB
13-
TebiByte = 1024 * 1024 * 1024 * 1024 // TiB
14-
15-
// shorthands
16-
KiB = KibiByte
17-
MB = MegaByte
18-
MiB = MebiByte
19-
GB = GigaByte
20-
GiB = GibiByte
21-
TiB = TebiByte
22-
)
23-
245
// These constants are set during buildtime using additional
256
// compiler flags. Not all of them are necessarily defined
267
// because RPMs can be build from a tarball and spec file without

Diff for: internal/common/helpers.go

-50
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import (
55
"fmt"
66
"io"
77
"os/exec"
8-
"regexp"
98
"sort"
10-
"strconv"
119
"strings"
1210
)
1311

@@ -27,54 +25,6 @@ func IsStringInSortedSlice(slice []string, s string) bool {
2725
return false
2826
}
2927

30-
// DataSizeToUint64 converts a size specified as a string in KB/KiB/MB/etc. to
31-
// a number of bytes represented by uint64.
32-
func DataSizeToUint64(size string) (uint64, error) {
33-
// Pre-process the input
34-
size = strings.TrimSpace(size)
35-
36-
// Get the number from the string
37-
plain_number := regexp.MustCompile(`[[:digit:]]+`)
38-
number_as_str := plain_number.FindString(size)
39-
if number_as_str == "" {
40-
return 0, fmt.Errorf("the size string doesn't contain any number: %s", size)
41-
}
42-
43-
// Parse the number into integer
44-
return_size, err := strconv.ParseUint(number_as_str, 10, 64)
45-
if err != nil {
46-
return 0, fmt.Errorf("failed to parse size as integer: %s", number_as_str)
47-
}
48-
49-
// List of all supported units (from kB to TB and KiB to TiB)
50-
supported_units := []struct {
51-
re *regexp.Regexp
52-
multiple uint64
53-
}{
54-
{regexp.MustCompile(`^\s*[[:digit:]]+\s*kB$`), KiloByte},
55-
{regexp.MustCompile(`^\s*[[:digit:]]+\s*KiB$`), KibiByte},
56-
{regexp.MustCompile(`^\s*[[:digit:]]+\s*MB$`), MegaByte},
57-
{regexp.MustCompile(`^\s*[[:digit:]]+\s*MiB$`), MebiByte},
58-
{regexp.MustCompile(`^\s*[[:digit:]]+\s*GB$`), GigaByte},
59-
{regexp.MustCompile(`^\s*[[:digit:]]+\s*GiB$`), GibiByte},
60-
{regexp.MustCompile(`^\s*[[:digit:]]+\s*TB$`), TeraByte},
61-
{regexp.MustCompile(`^\s*[[:digit:]]+\s*TiB$`), TebiByte},
62-
{regexp.MustCompile(`^\s*[[:digit:]]+$`), 1},
63-
}
64-
65-
for _, unit := range supported_units {
66-
if unit.re.MatchString(size) {
67-
return_size *= unit.multiple
68-
return return_size, nil
69-
}
70-
}
71-
72-
// In case the strign didn't match any of the above regexes, return nil
73-
// even if a number was found. This is to prevent users from submitting
74-
// unknown units.
75-
return 0, fmt.Errorf("unknown data size units in string: %s", size)
76-
}
77-
7828
// NopSeekCloser returns an io.ReadSeekCloser with a no-op Close method
7929
// wrapping the provided io.ReadSeeker r.
8030
func NopSeekCloser(r io.ReadSeeker) io.ReadSeekCloser {

Diff for: internal/common/helpers_test.go

-38
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"testing"
66

77
"github.com/stretchr/testify/assert"
8-
"github.com/stretchr/testify/require"
98
)
109

1110
func TestPanicOnError(t *testing.T) {
@@ -20,43 +19,6 @@ func TestIsStringInSortedSlice(t *testing.T) {
2019
assert.False(t, IsStringInSortedSlice([]string{}, "homer"))
2120
}
2221

23-
func TestDataSizeToUint64(t *testing.T) {
24-
cases := []struct {
25-
input string
26-
success bool
27-
output uint64
28-
}{
29-
{"123", true, 123},
30-
{"123 kB", true, 123000},
31-
{"123 KiB", true, 123 * 1024},
32-
{"123 MB", true, 123 * 1000 * 1000},
33-
{"123 MiB", true, 123 * 1024 * 1024},
34-
{"123 GB", true, 123 * 1000 * 1000 * 1000},
35-
{"123 GiB", true, 123 * 1024 * 1024 * 1024},
36-
{"123 TB", true, 123 * 1000 * 1000 * 1000 * 1000},
37-
{"123 TiB", true, 123 * 1024 * 1024 * 1024 * 1024},
38-
{"123kB", true, 123000},
39-
{"123KiB", true, 123 * 1024},
40-
{" 123 ", true, 123},
41-
{" 123kB ", true, 123000},
42-
{" 123KiB ", true, 123 * 1024},
43-
{"123 KB", false, 0},
44-
{"123 mb", false, 0},
45-
{"123 PB", false, 0},
46-
{"123 PiB", false, 0},
47-
}
48-
49-
for _, c := range cases {
50-
result, err := DataSizeToUint64(c.input)
51-
if c.success {
52-
require.Nil(t, err)
53-
assert.EqualValues(t, c.output, result)
54-
} else {
55-
assert.NotNil(t, err)
56-
}
57-
}
58-
}
59-
6022
func TestSystemdMountUnit(t *testing.T) {
6123
for _, tc := range []struct {
6224
mountpoint string

Diff for: pkg/datasizes/constants.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package datasizes
2+
3+
const (
4+
KiloByte = 1000 // kB
5+
KibiByte = 1024 // KiB
6+
MegaByte = 1000 * 1000 // MB
7+
MebiByte = 1024 * 1024 // MiB
8+
GigaByte = 1000 * 1000 * 1000 // GB
9+
GibiByte = 1024 * 1024 * 1024 // GiB
10+
TeraByte = 1000 * 1000 * 1000 * 1000 // TB
11+
TebiByte = 1024 * 1024 * 1024 * 1024 // TiB
12+
13+
// shorthands
14+
KiB = KibiByte
15+
MB = MegaByte
16+
MiB = MebiByte
17+
GB = GigaByte
18+
GiB = GibiByte
19+
TiB = TebiByte
20+
)

Diff for: pkg/datasizes/parse.go

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package datasizes
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strconv"
7+
"strings"
8+
)
9+
10+
// Parse converts a size specified as a string in KB/KiB/MB/etc. to
11+
// a number of bytes represented by uint64.
12+
func Parse(size string) (uint64, error) {
13+
// Pre-process the input
14+
size = strings.TrimSpace(size)
15+
16+
// Get the number from the string
17+
plain_number := regexp.MustCompile(`[[:digit:]]+`)
18+
number_as_str := plain_number.FindString(size)
19+
if number_as_str == "" {
20+
return 0, fmt.Errorf("the size string doesn't contain any number: %s", size)
21+
}
22+
23+
// Parse the number into integer
24+
return_size, err := strconv.ParseUint(number_as_str, 10, 64)
25+
if err != nil {
26+
return 0, fmt.Errorf("failed to parse size as integer: %s", number_as_str)
27+
}
28+
29+
// List of all supported units (from kB to TB and KiB to TiB)
30+
supported_units := []struct {
31+
re *regexp.Regexp
32+
multiple uint64
33+
}{
34+
{regexp.MustCompile(`^\s*[[:digit:]]+\s*kB$`), KiloByte},
35+
{regexp.MustCompile(`^\s*[[:digit:]]+\s*KiB$`), KibiByte},
36+
{regexp.MustCompile(`^\s*[[:digit:]]+\s*MB$`), MegaByte},
37+
{regexp.MustCompile(`^\s*[[:digit:]]+\s*MiB$`), MebiByte},
38+
{regexp.MustCompile(`^\s*[[:digit:]]+\s*GB$`), GigaByte},
39+
{regexp.MustCompile(`^\s*[[:digit:]]+\s*GiB$`), GibiByte},
40+
{regexp.MustCompile(`^\s*[[:digit:]]+\s*TB$`), TeraByte},
41+
{regexp.MustCompile(`^\s*[[:digit:]]+\s*TiB$`), TebiByte},
42+
{regexp.MustCompile(`^\s*[[:digit:]]+$`), 1},
43+
}
44+
45+
for _, unit := range supported_units {
46+
if unit.re.MatchString(size) {
47+
return_size *= unit.multiple
48+
return return_size, nil
49+
}
50+
}
51+
52+
// In case the strign didn't match any of the above regexes, return nil
53+
// even if a number was found. This is to prevent users from submitting
54+
// unknown units.
55+
return 0, fmt.Errorf("unknown data size units in string: %s", size)
56+
}

Diff for: pkg/datasizes/parse_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package datasizes_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
8+
9+
"github.com/osbuild/images/pkg/datasizes"
10+
)
11+
12+
func TestDataSizeToUint64(t *testing.T) {
13+
cases := []struct {
14+
input string
15+
success bool
16+
output uint64
17+
}{
18+
{"123", true, 123},
19+
{"123 kB", true, 123000},
20+
{"123 KiB", true, 123 * 1024},
21+
{"123 MB", true, 123 * 1000 * 1000},
22+
{"123 MiB", true, 123 * 1024 * 1024},
23+
{"123 GB", true, 123 * 1000 * 1000 * 1000},
24+
{"123 GiB", true, 123 * 1024 * 1024 * 1024},
25+
{"123 TB", true, 123 * 1000 * 1000 * 1000 * 1000},
26+
{"123 TiB", true, 123 * 1024 * 1024 * 1024 * 1024},
27+
{"123kB", true, 123000},
28+
{"123KiB", true, 123 * 1024},
29+
{" 123 ", true, 123},
30+
{" 123kB ", true, 123000},
31+
{" 123KiB ", true, 123 * 1024},
32+
{"123 KB", false, 0},
33+
{"123 mb", false, 0},
34+
{"123 PB", false, 0},
35+
{"123 PiB", false, 0},
36+
}
37+
38+
for _, c := range cases {
39+
result, err := datasizes.Parse(c.input)
40+
if c.success {
41+
require.Nil(t, err)
42+
assert.EqualValues(t, c.output, result)
43+
} else {
44+
assert.NotNil(t, err)
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)