github.com/coreservice-io/utils@v0.3.0/bytes_util/convert.go (about) 1 package bytes_util 2 3 import ( 4 "fmt" 5 "regexp" 6 "strconv" 7 "strings" 8 ) 9 10 type ( 11 // Bytes struct 12 Bytes struct{} 13 ) 14 15 const ( 16 _ = 1.0 << (10 * iota) // ignore first value by assigning to blank identifier 17 KB 18 MB 19 GB 20 TB 21 PB 22 EB 23 ) 24 25 var ( 26 pattern = regexp.MustCompile(`(?i)^(-?\d+(?:\.\d+)?)\s?([KMGTPE]B?|B?)$`) 27 ) 28 29 // Format formats bytes integer to human readable string. 30 // For example, 31323 bytes will return 30.59KB. 31 func Format(b int64) string { 32 multiple := "" 33 value := float64(b) 34 35 switch { 36 case b >= EB: 37 value /= EB 38 multiple = "EB" 39 case b >= PB: 40 value /= PB 41 multiple = "PB" 42 case b >= TB: 43 value /= TB 44 multiple = "TB" 45 case b >= GB: 46 value /= GB 47 multiple = "GB" 48 case b >= MB: 49 value /= MB 50 multiple = "MB" 51 case b >= KB: 52 value /= KB 53 multiple = "KB" 54 case b == 0: 55 return "0" 56 default: 57 return strconv.FormatInt(b, 10) + "B" 58 } 59 60 return fmt.Sprintf("%.2f%s", value, multiple) 61 } 62 63 // Parse parses human readable bytes string to bytes integer. 64 // For example, 6GB (6G is also valid) will return 6442450944. 65 func Parse(value string) (i int64, err error) { 66 value = strings.Trim(value, " ") 67 value = strings.Trim(value, ",") 68 parts := pattern.FindStringSubmatch(value) 69 if len(parts) < 3 { 70 return 0, fmt.Errorf("error parsing value=%s", value) 71 } 72 bytesString := parts[1] 73 multiple := strings.ToUpper(parts[2]) 74 bytes, err := strconv.ParseFloat(bytesString, 64) 75 if err != nil { 76 return 77 } 78 79 switch multiple { 80 default: 81 return int64(bytes), nil 82 case "K", "KB": 83 return int64(bytes * KB), nil 84 case "M", "MB": 85 return int64(bytes * MB), nil 86 case "G", "GB": 87 return int64(bytes * GB), nil 88 case "T", "TB": 89 return int64(bytes * TB), nil 90 case "P", "PB": 91 return int64(bytes * PB), nil 92 case "E", "EB": 93 return int64(bytes * EB), nil 94 } 95 }