New Upstream Release - golang-github-docker-go-units
Ready changes
Summary
Merged new upstream version: 0.5.0 (was: 0.4.0).
Resulting package
Built on 2022-12-01T00:35 (took 4m4s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases golang-github-docker-go-units-dev
Lintian Result
Diff
diff --git a/debian/changelog b/debian/changelog
index 70ed0bc..08318f8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-github-docker-go-units (0.5.0-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Thu, 01 Dec 2022 00:31:51 -0000
+
golang-github-docker-go-units (0.4.0-4) unstable; urgency=medium
* Team upload.
diff --git a/size.go b/size.go
index 85f6ab0..c245a89 100644
--- a/size.go
+++ b/size.go
@@ -2,7 +2,6 @@ package units
import (
"fmt"
- "regexp"
"strconv"
"strings"
)
@@ -26,16 +25,17 @@ const (
PiB = 1024 * TiB
)
-type unitMap map[string]int64
+type unitMap map[byte]int64
var (
- decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB}
- binaryMap = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB}
- sizeRegex = regexp.MustCompile(`^(\d+(\.\d+)*) ?([kKmMgGtTpP])?[iI]?[bB]?$`)
+ decimalMap = unitMap{'k': KB, 'm': MB, 'g': GB, 't': TB, 'p': PB}
+ binaryMap = unitMap{'k': KiB, 'm': MiB, 'g': GiB, 't': TiB, 'p': PiB}
)
-var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
-var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
+var (
+ decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
+ binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
+)
func getSizeAndUnit(size float64, base float64, _map []string) (float64, string) {
i := 0
@@ -89,20 +89,66 @@ func RAMInBytes(size string) (int64, error) {
// Parses the human-readable size string into the amount it represents.
func parseSize(sizeStr string, uMap unitMap) (int64, error) {
- matches := sizeRegex.FindStringSubmatch(sizeStr)
- if len(matches) != 4 {
+ // TODO: rewrite to use strings.Cut if there's a space
+ // once Go < 1.18 is deprecated.
+ sep := strings.LastIndexAny(sizeStr, "01234567890. ")
+ if sep == -1 {
+ // There should be at least a digit.
return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
}
+ var num, sfx string
+ if sizeStr[sep] != ' ' {
+ num = sizeStr[:sep+1]
+ sfx = sizeStr[sep+1:]
+ } else {
+ // Omit the space separator.
+ num = sizeStr[:sep]
+ sfx = sizeStr[sep+1:]
+ }
- size, err := strconv.ParseFloat(matches[1], 64)
+ size, err := strconv.ParseFloat(num, 64)
if err != nil {
return -1, err
}
+ // Backward compatibility: reject negative sizes.
+ if size < 0 {
+ return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
+ }
+
+ if len(sfx) == 0 {
+ return int64(size), nil
+ }
- unitPrefix := strings.ToLower(matches[3])
- if mul, ok := uMap[unitPrefix]; ok {
+ // Process the suffix.
+
+ if len(sfx) > 3 { // Too long.
+ goto badSuffix
+ }
+ sfx = strings.ToLower(sfx)
+ // Trivial case: b suffix.
+ if sfx[0] == 'b' {
+ if len(sfx) > 1 { // no extra characters allowed after b.
+ goto badSuffix
+ }
+ return int64(size), nil
+ }
+ // A suffix from the map.
+ if mul, ok := uMap[sfx[0]]; ok {
size *= float64(mul)
+ } else {
+ goto badSuffix
+ }
+
+ // The suffix may have extra "b" or "ib" (e.g. KiB or MB).
+ switch {
+ case len(sfx) == 2 && sfx[1] != 'b':
+ goto badSuffix
+ case len(sfx) == 3 && sfx[1:] != "ib":
+ goto badSuffix
}
return int64(size), nil
+
+badSuffix:
+ return -1, fmt.Errorf("invalid suffix: '%s'", sfx)
}
diff --git a/size_test.go b/size_test.go
index ab389ec..f9b1d59 100644
--- a/size_test.go
+++ b/size_test.go
@@ -83,6 +83,10 @@ func TestHumanSize(t *testing.T) {
}
func TestFromHumanSize(t *testing.T) {
+ assertSuccessEquals(t, 0, FromHumanSize, "0")
+ assertSuccessEquals(t, 0, FromHumanSize, "0b")
+ assertSuccessEquals(t, 0, FromHumanSize, "0B")
+ assertSuccessEquals(t, 0, FromHumanSize, "0 B")
assertSuccessEquals(t, 32, FromHumanSize, "32")
assertSuccessEquals(t, 32, FromHumanSize, "32b")
assertSuccessEquals(t, 32, FromHumanSize, "32B")
@@ -98,11 +102,59 @@ func TestFromHumanSize(t *testing.T) {
assertSuccessEquals(t, 32.5*KB, FromHumanSize, "32.5kB")
assertSuccessEquals(t, 32.5*KB, FromHumanSize, "32.5 kB")
assertSuccessEquals(t, 32, FromHumanSize, "32.5 B")
+ assertSuccessEquals(t, 300, FromHumanSize, "0.3 K")
+ assertSuccessEquals(t, 300, FromHumanSize, ".3kB")
+
+ assertSuccessEquals(t, 0, FromHumanSize, "0.")
+ assertSuccessEquals(t, 0, FromHumanSize, "0. ")
+ assertSuccessEquals(t, 0, FromHumanSize, "0.b")
+ assertSuccessEquals(t, 0, FromHumanSize, "0.B")
+ assertSuccessEquals(t, 0, FromHumanSize, "-0")
+ assertSuccessEquals(t, 0, FromHumanSize, "-0b")
+ assertSuccessEquals(t, 0, FromHumanSize, "-0B")
+ assertSuccessEquals(t, 0, FromHumanSize, "-0 b")
+ assertSuccessEquals(t, 0, FromHumanSize, "-0 B")
+ assertSuccessEquals(t, 32, FromHumanSize, "32.")
+ assertSuccessEquals(t, 32, FromHumanSize, "32.b")
+ assertSuccessEquals(t, 32, FromHumanSize, "32.B")
+ assertSuccessEquals(t, 32, FromHumanSize, "32. b")
+ assertSuccessEquals(t, 32, FromHumanSize, "32. B")
+
+ // We do not tolerate extra leading or trailing spaces
+ // (except for a space after the number and a missing suffix).
+ assertSuccessEquals(t, 0, FromHumanSize, "0 ")
+
+ assertError(t, FromHumanSize, " 0")
+ assertError(t, FromHumanSize, " 0b")
+ assertError(t, FromHumanSize, " 0B")
+ assertError(t, FromHumanSize, " 0 B")
+ assertError(t, FromHumanSize, "0b ")
+ assertError(t, FromHumanSize, "0B ")
+ assertError(t, FromHumanSize, "0 B ")
assertError(t, FromHumanSize, "")
assertError(t, FromHumanSize, "hello")
+ assertError(t, FromHumanSize, ".")
+ assertError(t, FromHumanSize, ". ")
+ assertError(t, FromHumanSize, " ")
+ assertError(t, FromHumanSize, " ")
+ assertError(t, FromHumanSize, " .")
+ assertError(t, FromHumanSize, " . ")
assertError(t, FromHumanSize, "-32")
- assertError(t, FromHumanSize, ".3kB")
+ assertError(t, FromHumanSize, "-32b")
+ assertError(t, FromHumanSize, "-32B")
+ assertError(t, FromHumanSize, "-32 b")
+ assertError(t, FromHumanSize, "-32 B")
+ assertError(t, FromHumanSize, "32b.")
+ assertError(t, FromHumanSize, "32B.")
+ assertError(t, FromHumanSize, "32 b.")
+ assertError(t, FromHumanSize, "32 B.")
+ assertError(t, FromHumanSize, "32 bb")
+ assertError(t, FromHumanSize, "32 BB")
+ assertError(t, FromHumanSize, "32 b b")
+ assertError(t, FromHumanSize, "32 B B")
+ assertError(t, FromHumanSize, "32 b")
+ assertError(t, FromHumanSize, "32 B")
assertError(t, FromHumanSize, " 32 ")
assertError(t, FromHumanSize, "32m b")
assertError(t, FromHumanSize, "32bm")
@@ -128,6 +180,8 @@ func TestRAMInBytes(t *testing.T) {
assertSuccessEquals(t, 32, RAMInBytes, "32.3")
tmp := 32.3 * MiB
assertSuccessEquals(t, int64(tmp), RAMInBytes, "32.3 mb")
+ tmp = 0.3 * MiB
+ assertSuccessEquals(t, int64(tmp), RAMInBytes, "0.3MB")
assertError(t, RAMInBytes, "")
assertError(t, RAMInBytes, "hello")
@@ -137,7 +191,20 @@ func TestRAMInBytes(t *testing.T) {
assertError(t, RAMInBytes, "32bm")
}
+func BenchmarkParseSize(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, s := range []string{
+ "", "32", "32b", "32 B", "32k", "32.5 K", "32kb", "32 Kb",
+ "32.8Mb", "32.9Gb", "32.777Tb", "32Pb", "0.3Mb", "-1",
+ } {
+ FromHumanSize(s)
+ RAMInBytes(s)
+ }
+ }
+}
+
func assertEquals(t *testing.T, expected, actual interface{}) {
+ t.Helper()
if expected != actual {
t.Errorf("Expected '%v' but got '%v'", expected, actual)
}
@@ -153,6 +220,7 @@ func (fn parseFn) String() string {
}
func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) {
+ t.Helper()
res, err := fn(arg)
if err != nil || res != expected {
t.Errorf("%s(\"%s\") -> expected '%d' but got '%d' with error '%v'", fn, arg, expected, res, err)
@@ -160,6 +228,7 @@ func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) {
}
func assertError(t *testing.T, fn parseFn, arg string) {
+ t.Helper()
res, err := fn(arg)
if err == nil && res != -1 {
t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res)
Debdiff
File lists identical (after any substitutions)
No differences were encountered in the control files