github.com/kubesphere/s2irun@v3.2.1+incompatible/pkg/utils/bytefmt/bytes.go (about) 1 // Package bytefmt contains helper methods and constants for converting to and from a human-readable byte format. 2 // 3 // bytefmt.ByteSize(100.5*bytefmt.MEGABYTE) // "100.5M" 4 // bytefmt.ByteSize(uint64(1024)) // "1K" 5 // 6 package bytefmt 7 8 import ( 9 "errors" 10 "strconv" 11 "strings" 12 "unicode" 13 ) 14 15 const ( 16 BYTE = 1 << (10 * iota) 17 KILOBYTE 18 MEGABYTE 19 GIGABYTE 20 TERABYTE 21 PETABYTE 22 EXABYTE 23 ) 24 25 var invalidByteQuantityError = errors.New("byte quantity must be a positive integer with a unit of measurement like M, MB, MiB, G, GiB, or GB") 26 27 // ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth. The following units are available: 28 // E: Exabyte 29 // P: Petabyte 30 // T: Terabyte 31 // G: Gigabyte 32 // M: Megabyte 33 // K: Kilobyte 34 // B: Byte 35 // The unit that results in the smallest number greater than or equal to 1 is always chosen. 36 func ByteSize(bytes uint64) string { 37 unit := "" 38 value := float64(bytes) 39 40 switch { 41 case bytes >= EXABYTE: 42 unit = "E" 43 value = value / EXABYTE 44 case bytes >= PETABYTE: 45 unit = "P" 46 value = value / PETABYTE 47 case bytes >= TERABYTE: 48 unit = "T" 49 value = value / TERABYTE 50 case bytes >= GIGABYTE: 51 unit = "G" 52 value = value / GIGABYTE 53 case bytes >= MEGABYTE: 54 unit = "M" 55 value = value / MEGABYTE 56 case bytes >= KILOBYTE: 57 unit = "K" 58 value = value / KILOBYTE 59 case bytes >= BYTE: 60 unit = "B" 61 case bytes == 0: 62 return "0" 63 } 64 65 result := strconv.FormatFloat(value, 'f', 1, 64) 66 result = strings.TrimSuffix(result, ".0") 67 return result + unit 68 } 69 70 // ToMegabytes parses a string formatted by ByteSize as megabytes. 71 func ToMegabytes(s string) (uint64, error) { 72 bytes, err := ToBytes(s) 73 if err != nil { 74 return 0, err 75 } 76 77 return bytes / MEGABYTE, nil 78 } 79 80 // ToBytes parses a string formatted by ByteSize as bytes. Note binary-prefixed and SI prefixed units both mean a base-2 units 81 // KB = K = KiB = 1024 82 // MB = M = MiB = 1024 * K 83 // GB = G = GiB = 1024 * M 84 // TB = T = TiB = 1024 * G 85 // PB = P = PiB = 1024 * T 86 // EB = E = EiB = 1024 * P 87 func ToBytes(s string) (uint64, error) { 88 s = strings.TrimSpace(s) 89 s = strings.ToUpper(s) 90 91 i := strings.IndexFunc(s, unicode.IsLetter) 92 93 if i == -1 { 94 return 0, invalidByteQuantityError 95 } 96 97 bytesString, multiple := s[:i], s[i:] 98 bytes, err := strconv.ParseFloat(bytesString, 64) 99 if err != nil || bytes <= 0 { 100 return 0, invalidByteQuantityError 101 } 102 103 switch multiple { 104 case "E", "EB", "EIB": 105 return uint64(bytes * EXABYTE), nil 106 case "P", "PB", "PIB": 107 return uint64(bytes * PETABYTE), nil 108 case "T", "TB", "TIB": 109 return uint64(bytes * TERABYTE), nil 110 case "G", "GB", "GIB": 111 return uint64(bytes * GIGABYTE), nil 112 case "M", "MB", "MIB": 113 return uint64(bytes * MEGABYTE), nil 114 case "K", "KB", "KIB": 115 return uint64(bytes * KILOBYTE), nil 116 case "B": 117 return uint64(bytes), nil 118 default: 119 return 0, invalidByteQuantityError 120 } 121 }