github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/common/units/bytesize.go (about)

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