mirror of https://github.com/XTLS/Xray-core
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
1.8 KiB
100 lines
1.8 KiB
package units |
|
|
|
import ( |
|
"errors" |
|
"strconv" |
|
"strings" |
|
"unicode" |
|
) |
|
|
|
var ( |
|
errInvalidSize = errors.New("invalid size") |
|
errInvalidUnit = errors.New("invalid or unsupported unit") |
|
) |
|
|
|
// ByteSize is the size of bytes |
|
type ByteSize uint64 |
|
|
|
const ( |
|
_ = iota |
|
// KB = 1KB |
|
KB ByteSize = 1 << (10 * iota) |
|
// MB = 1MB |
|
MB |
|
// GB = 1GB |
|
GB |
|
// TB = 1TB |
|
TB |
|
// PB = 1PB |
|
PB |
|
// EB = 1EB |
|
EB |
|
) |
|
|
|
func (b ByteSize) String() string { |
|
unit := "" |
|
value := float64(0) |
|
switch { |
|
case b == 0: |
|
return "0" |
|
case b < KB: |
|
unit = "B" |
|
value = float64(b) |
|
case b < MB: |
|
unit = "KB" |
|
value = float64(b) / float64(KB) |
|
case b < GB: |
|
unit = "MB" |
|
value = float64(b) / float64(MB) |
|
case b < TB: |
|
unit = "GB" |
|
value = float64(b) / float64(GB) |
|
case b < PB: |
|
unit = "TB" |
|
value = float64(b) / float64(TB) |
|
case b < EB: |
|
unit = "PB" |
|
value = float64(b) / float64(PB) |
|
default: |
|
unit = "EB" |
|
value = float64(b) / float64(EB) |
|
} |
|
result := strconv.FormatFloat(value, 'f', 2, 64) |
|
result = strings.TrimSuffix(result, ".0") |
|
return result + unit |
|
} |
|
|
|
// Parse parses ByteSize from string |
|
func (b *ByteSize) Parse(s string) error { |
|
s = strings.TrimSpace(s) |
|
s = strings.ToUpper(s) |
|
i := strings.IndexFunc(s, unicode.IsLetter) |
|
if i == -1 { |
|
return errInvalidUnit |
|
} |
|
|
|
bytesString, multiple := s[:i], s[i:] |
|
bytes, err := strconv.ParseFloat(bytesString, 64) |
|
if err != nil || bytes <= 0 { |
|
return errInvalidSize |
|
} |
|
switch multiple { |
|
case "B": |
|
*b = ByteSize(bytes) |
|
case "K", "KB", "KIB": |
|
*b = ByteSize(bytes * float64(KB)) |
|
case "M", "MB", "MIB": |
|
*b = ByteSize(bytes * float64(MB)) |
|
case "G", "GB", "GIB": |
|
*b = ByteSize(bytes * float64(GB)) |
|
case "T", "TB", "TIB": |
|
*b = ByteSize(bytes * float64(TB)) |
|
case "P", "PB", "PIB": |
|
*b = ByteSize(bytes * float64(PB)) |
|
case "E", "EB", "EIB": |
|
*b = ByteSize(bytes * float64(EB)) |
|
default: |
|
return errInvalidUnit |
|
} |
|
return nil |
|
}
|
|
|