Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions size.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const (
PiB = 1024 * TiB
)

type unitMap map[string]int64
type unitMap map[string]uint64

var (
decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB}
Expand Down Expand Up @@ -75,34 +75,35 @@ func BytesSize(size float64) string {

// FromHumanSize returns an integer from a human-readable specification of a
// size using SI standard (eg. "44kB", "17MB").
func FromHumanSize(size string) (int64, error) {
func FromHumanSize(size string) (uint64, error) {
return parseSize(size, decimalMap)
}

// RAMInBytes parses a human-readable string representing an amount of RAM
// in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and
// returns the number of bytes, or -1 if the string is unparseable.
// returns the number of bytes, or 0 and corresponding error if the string
// is unparseable.
// Units are case-insensitive, and the 'b' suffix is optional.
func RAMInBytes(size string) (int64, error) {
func RAMInBytes(size string) (uint64, error) {
return parseSize(size, binaryMap)
}

// Parses the human-readable size string into the amount it represents.
func parseSize(sizeStr string, uMap unitMap) (int64, error) {
func parseSize(sizeStr string, uMap unitMap) (uint64, error) {
matches := sizeRegex.FindStringSubmatch(sizeStr)
if len(matches) != 4 {
return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
return 0, fmt.Errorf("invalid size: '%s'", sizeStr)
}

size, err := strconv.ParseFloat(matches[1], 64)
if err != nil {
return -1, err
return 0, err
}

unitPrefix := strings.ToLower(matches[3])
if mul, ok := uMap[unitPrefix]; ok {
size *= float64(mul)
}

return int64(size), nil
return uint64(size), nil
}
8 changes: 4 additions & 4 deletions size_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func TestRAMInBytes(t *testing.T) {

assertSuccessEquals(t, 32, RAMInBytes, "32.3")
tmp := 32.3 * MiB
assertSuccessEquals(t, int64(tmp), RAMInBytes, "32.3 mb")
assertSuccessEquals(t, uint64(tmp), RAMInBytes, "32.3 mb")

assertError(t, RAMInBytes, "")
assertError(t, RAMInBytes, "hello")
Expand All @@ -142,15 +142,15 @@ func assertEquals(t *testing.T, expected, actual interface{}) {
}

// func that maps to the parse function signatures as testing abstraction
type parseFn func(string) (int64, error)
type parseFn func(string) (uint64, error)

// Define 'String()' for pretty-print
func (fn parseFn) String() string {
fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
return fnName[strings.LastIndex(fnName, ".")+1:]
}

func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) {
func assertSuccessEquals(t *testing.T, expected uint64, fn parseFn, arg string) {
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)
Expand All @@ -159,7 +159,7 @@ func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) {

func assertError(t *testing.T, fn parseFn, arg string) {
res, err := fn(arg)
if err == nil && res != -1 {
if err == nil && res != 0 {
t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res)
}
}