bytesize.go 1.8 KB

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