github.com/GuanceCloud/cliutils@v1.1.21/pprofparser/domain/quantity/unit.go (about)

     1  package quantity
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strings"
     7  	"time"
     8  )
     9  
    10  var (
    11  	MemoryDisplayName     = "digital"
    12  	MemoryDefaultUnitFlag = "B"
    13  
    14  	DurationDisplayName     = "time"
    15  	DurationDefaultUnitFlag = "μs"
    16  )
    17  
    18  var UnknownUnit = &Unit{Kind: UnknownKind, Name: "unknown"}
    19  
    20  var (
    21  	NanoSecond  = &Unit{Kind: Duration, Base: int64(time.Nanosecond), Name: "ns"}
    22  	MicroSecond = &Unit{Kind: Duration, Base: int64(time.Microsecond), Name: "us"}
    23  	MilliSecond = &Unit{Kind: Duration, Base: int64(time.Millisecond), Name: "ms"}
    24  	Second      = &Unit{Kind: Duration, Base: int64(time.Second), Name: "s"}
    25  	Minute      = &Unit{Kind: Duration, Base: int64(time.Minute), Name: "m"}
    26  	Hour        = &Unit{Kind: Duration, Base: int64(time.Hour), Name: "h"}
    27  )
    28  
    29  var (
    30  	CountUnit = &Unit{Kind: Count, Base: 1, Name: ""}
    31  )
    32  
    33  var (
    34  	Byte     = &Unit{Kind: Memory, Base: 1, Name: "Bytes"}
    35  	KiloByte = &Unit{Kind: Memory, Base: 1 << 10, Name: "KB"}
    36  	MegaByte = &Unit{Kind: Memory, Base: 1 << 20, Name: "MB"}
    37  	GigaByte = &Unit{Kind: Memory, Base: 1 << 30, Name: "GB"}
    38  	TeraByte = &Unit{Kind: Memory, Base: 1 << 40, Name: "TB"}
    39  	PetaByte = &Unit{Kind: Memory, Base: 1 << 50, Name: "PB"}
    40  )
    41  
    42  var (
    43  	memoryUnitMaps = map[string]*Unit{
    44  		"bytes": Byte,
    45  		"byte":  Byte,
    46  		"b":     Byte,
    47  
    48  		"kilobytes": KiloByte,
    49  		"kilobyte":  KiloByte, // 1000
    50  		"kibibytes": KiloByte,
    51  		"kibibyte":  KiloByte, // 1024
    52  		"kib":       KiloByte,
    53  		"kb":        KiloByte,
    54  
    55  		"megabytes": MegaByte,
    56  		"megabyte":  MegaByte,
    57  		"megibytes": MegaByte,
    58  		"megibyte":  MegaByte,
    59  		"mib":       MegaByte,
    60  		"mb":        MegaByte,
    61  
    62  		"gigabytes": GigaByte,
    63  		"gigabyte":  GigaByte,
    64  		"gigibytes": GigaByte,
    65  		"gigibyte":  GigaByte,
    66  		"gib":       GigaByte,
    67  		"gb":        GigaByte,
    68  
    69  		"terabytes":     TeraByte,
    70  		"terabyte":      TeraByte,
    71  		"tebibytes":     TeraByte,
    72  		"tebibyte":      TeraByte,
    73  		"trillionbytes": TeraByte,
    74  		"trillionbyte":  TeraByte,
    75  		"tib":           TeraByte,
    76  		"tb":            TeraByte,
    77  
    78  		"petabytes": PetaByte,
    79  		"petabyte":  PetaByte,
    80  		"pebibytes": PetaByte,
    81  		"pebibyte":  PetaByte,
    82  		"pib":       PetaByte,
    83  		"pb":        PetaByte,
    84  	}
    85  
    86  	durationUnitMaps = map[string]*Unit{
    87  		"nanoseconds": NanoSecond,
    88  		"nanosecond":  NanoSecond,
    89  		"ns":          NanoSecond,
    90  
    91  		"microseconds": MicroSecond,
    92  		"microsecond":  MicroSecond,
    93  		"us":           MicroSecond,
    94  		"µs":           MicroSecond,
    95  
    96  		"milliseconds": MilliSecond,
    97  		"millisecond":  MilliSecond,
    98  		"ms":           MilliSecond,
    99  
   100  		"seconds": Second,
   101  		"second":  Second,
   102  		"s":       Second,
   103  
   104  		"minutes": Minute,
   105  		"minute":  Minute,
   106  		"m":       Minute,
   107  
   108  		"hours": Hour,
   109  		"hour":  Hour,
   110  		"h":     Hour,
   111  	}
   112  )
   113  
   114  type Unit struct {
   115  	Kind *Kind
   116  	Base int64
   117  	Name string
   118  }
   119  
   120  func (u *Unit) String() string {
   121  	return u.Name
   122  }
   123  
   124  // ConvertTo convert value for Unit u to Unit target
   125  func (u *Unit) ConvertTo(target *Unit, value int64) (int64, error) {
   126  	if u.Kind != target.Kind {
   127  		return 0, fmt.Errorf("unit kinds are not compatiable")
   128  	}
   129  	return value * u.Base / target.Base, nil
   130  }
   131  
   132  // ConvertToDefaultUnit convert value in Unit u to Unit Kind's default unit
   133  func (u *Unit) ConvertToDefaultUnit(value int64) int64 {
   134  	v, _ := u.ConvertTo(u.Kind.DefaultUnit, value)
   135  	return v
   136  }
   137  
   138  func (u *Unit) Quantity(v int64) *Quantity {
   139  	return &Quantity{
   140  		Unit:  u,
   141  		Value: v,
   142  	}
   143  }
   144  
   145  func (u *Unit) MarshalJSON() ([]byte, error) {
   146  	var flags []string
   147  
   148  	switch u.Kind {
   149  	case Memory:
   150  		flags = []string{MemoryDisplayName, MemoryDefaultUnitFlag}
   151  	case Duration:
   152  		flags = []string{DurationDisplayName, DurationDefaultUnitFlag}
   153  	default:
   154  		flags = make([]string, 0)
   155  	}
   156  	return json.Marshal(flags)
   157  }
   158  
   159  func parseDuration(s string) (*Unit, error) {
   160  	unit := strings.ToLower(strings.TrimSpace(s))
   161  	if u, ok := durationUnitMaps[unit]; ok {
   162  		return u, nil
   163  	}
   164  	switch {
   165  	case strings.HasPrefix(unit, "na"): // nano
   166  		return NanoSecond, nil
   167  	case strings.HasPrefix(unit, "mic"): // micro
   168  		return MicroSecond, nil
   169  	case strings.HasPrefix(unit, "mil"): // milli
   170  		return MilliSecond, nil
   171  	case strings.HasPrefix(unit, "min"): // minute
   172  		return Minute, nil
   173  	case strings.HasPrefix(unit, "hour"): // hour
   174  		return Hour, nil
   175  	case strings.HasPrefix(unit, "sec"): // second
   176  		return Second, nil
   177  	}
   178  	return nil, fmt.Errorf("can not resolve duration unit from [%s]", s)
   179  }
   180  
   181  func parseMemoryUnit(s string) (*Unit, error) {
   182  	unit := strings.ToLower(strings.TrimSpace(s))
   183  	if u, ok := memoryUnitMaps[unit]; ok {
   184  		return u, nil
   185  	}
   186  	switch {
   187  	case strings.HasPrefix(unit, "k"):
   188  		return KiloByte, nil
   189  	case strings.HasPrefix(unit, "m"):
   190  		return MegaByte, nil
   191  	case strings.HasPrefix(unit, "g"):
   192  		return GigaByte, nil
   193  	case strings.HasPrefix(unit, "t"):
   194  		return TeraByte, nil
   195  	case strings.HasPrefix(unit, "p"):
   196  		return PetaByte, nil
   197  	case strings.HasPrefix(unit, "byte"):
   198  		return Byte, nil
   199  	}
   200  	return nil, fmt.Errorf("can not resolve memory unit from [%s]", s)
   201  }
   202  
   203  func ParseUnit(kind *Kind, s string) (*Unit, error) {
   204  	switch kind {
   205  	case Count:
   206  		return CountUnit, nil
   207  	case Memory:
   208  		return parseMemoryUnit(s)
   209  	case Duration:
   210  		return parseDuration(s)
   211  	}
   212  	return nil, fmt.Errorf("unknown quantity kind")
   213  }