bytesize.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package units
  2. import (
  3. "errors"
  4. "strconv"
  5. "strings"
  6. "unicode"
  7. )
  8. var errInvalidSize = errors.New("invalid size")
  9. var errInvalidUnit = errors.New("invalid or unsupported unit")
  10. // ByteSize is the size of bytes
  11. type ByteSize uint64
  12. const (
  13. _ = iota
  14. // KB = 1KB
  15. KB ByteSize = 1 << (10 * iota)
  16. // MB = 1MB
  17. MB
  18. // GB = 1GB
  19. GB
  20. // TB = 1TB
  21. TB
  22. // PB = 1PB
  23. PB
  24. // EB = 1EB
  25. EB
  26. )
  27. func (b ByteSize) String() string {
  28. unit := ""
  29. value := float64(0)
  30. switch {
  31. case b == 0:
  32. return "0"
  33. case b < KB:
  34. unit = "B"
  35. value = float64(b)
  36. case b < MB:
  37. unit = "KB"
  38. value = float64(b) / float64(KB)
  39. case b < GB:
  40. unit = "MB"
  41. value = float64(b) / float64(MB)
  42. case b < TB:
  43. unit = "GB"
  44. value = float64(b) / float64(GB)
  45. case b < PB:
  46. unit = "TB"
  47. value = float64(b) / float64(TB)
  48. case b < EB:
  49. unit = "PB"
  50. value = float64(b) / float64(PB)
  51. default:
  52. unit = "EB"
  53. value = float64(b) / float64(EB)
  54. }
  55. result := strconv.FormatFloat(value, 'f', 2, 64)
  56. result = strings.TrimSuffix(result, ".0")
  57. return result + unit
  58. }
  59. // Parse parses ByteSize from string
  60. func (b *ByteSize) Parse(s string) error {
  61. s = strings.TrimSpace(s)
  62. s = strings.ToUpper(s)
  63. i := strings.IndexFunc(s, unicode.IsLetter)
  64. if i == -1 {
  65. return errInvalidUnit
  66. }
  67. bytesString, multiple := s[:i], s[i:]
  68. bytes, err := strconv.ParseFloat(bytesString, 64)
  69. if err != nil || bytes <= 0 {
  70. return errInvalidSize
  71. }
  72. switch multiple {
  73. case "B":
  74. *b = ByteSize(bytes)
  75. case "K", "KB", "KIB":
  76. *b = ByteSize(bytes * float64(KB))
  77. case "M", "MB", "MIB":
  78. *b = ByteSize(bytes * float64(MB))
  79. case "G", "GB", "GIB":
  80. *b = ByteSize(bytes * float64(GB))
  81. case "T", "TB", "TIB":
  82. *b = ByteSize(bytes * float64(TB))
  83. case "P", "PB", "PIB":
  84. *b = ByteSize(bytes * float64(PB))
  85. case "E", "EB", "EIB":
  86. *b = ByteSize(bytes * float64(EB))
  87. default:
  88. return errInvalidUnit
  89. }
  90. return nil
  91. }