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

     1  package quantity
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/GuanceCloud/cliutils/pprofparser/tools/mathtoolkit"
     8  )
     9  
    10  type Quantity struct {
    11  	Value int64
    12  	Unit  *Unit
    13  }
    14  
    15  func (q *Quantity) MarshalJSON() ([]byte, error) {
    16  	if q == nil {
    17  		return []byte("null"), nil
    18  	}
    19  	return []byte(fmt.Sprintf("\"%s\"", q.String())), nil
    20  }
    21  
    22  func (q *Quantity) SwitchToDefaultUnit() {
    23  	if q == nil || q.Unit == nil {
    24  		return
    25  	}
    26  	if q.Unit != q.Unit.Kind.DefaultUnit {
    27  		q.Value, _ = q.IntValueIn(q.Unit.Kind.DefaultUnit)
    28  		q.Unit = q.Unit.Kind.DefaultUnit
    29  	}
    30  }
    31  
    32  func (q *Quantity) String() string {
    33  	if q.Value == 0 {
    34  		return "No Data"
    35  	}
    36  	switch q.Unit.Kind {
    37  	case Count:
    38  		return fmt.Sprintf("%d", q.Value)
    39  	case Memory:
    40  		byt, _ := q.IntValueIn(Byte)
    41  		if byt >= GigaByte.Base {
    42  			gb, _ := q.DoubleValueIn(GigaByte)
    43  			return fmt.Sprintf("%.2f %s", gb, GigaByte)
    44  		} else if byt >= MegaByte.Base {
    45  			mb, _ := q.DoubleValueIn(MegaByte)
    46  			return fmt.Sprintf("%.2f %s", mb, MegaByte)
    47  		} else if byt >= KiloByte.Base {
    48  			kb, _ := q.DoubleValueIn(KiloByte)
    49  			return fmt.Sprintf("%.2f %s", kb, KiloByte)
    50  		}
    51  		return fmt.Sprintf("%d %s", byt, Byte)
    52  	case Duration:
    53  		td := q.toTimeDuration()
    54  		return td.String()
    55  	}
    56  	return fmt.Sprintf("%d %s", q.Value, q.Unit)
    57  }
    58  
    59  func (q *Quantity) DoubleValueIn(target *Unit) (float64, error) {
    60  	if q.Unit == target {
    61  		return float64(q.Value), nil
    62  	}
    63  	if q.Unit.Kind != target.Kind {
    64  		return 0, fmt.Errorf("can not convert [%s] to [%s], the kinds of the unit should be same", q.Unit, target)
    65  	}
    66  
    67  	return float64(q.Value) * (float64(q.Unit.Base) / float64(target.Base)), nil
    68  }
    69  
    70  func (q *Quantity) IntValueIn(target *Unit) (int64, error) {
    71  	if q.Unit == target {
    72  		return q.Value, nil
    73  	}
    74  	v, err := q.DoubleValueIn(target)
    75  	if err != nil {
    76  		return 0, err
    77  	}
    78  	return mathtoolkit.Trunc(v), nil
    79  }
    80  
    81  func (q *Quantity) Sub(sub *Quantity) *Quantity {
    82  	if q.Unit.Kind != sub.Unit.Kind {
    83  		panic("arithmetic operation between not matched unit kind")
    84  	}
    85  
    86  	m, n := q.Value, sub.Value
    87  
    88  	toUnit := q.Unit
    89  	if q.Unit.Base > sub.Unit.Base {
    90  		m, _ = q.IntValueIn(sub.Unit)
    91  		toUnit = sub.Unit
    92  	} else if q.Unit.Base < sub.Unit.Base {
    93  		n, _ = sub.IntValueIn(q.Unit)
    94  	}
    95  
    96  	return toUnit.Quantity(m - n)
    97  }
    98  
    99  func (q *Quantity) toTimeDuration() time.Duration {
   100  	if q.Unit.Kind != Duration {
   101  		panic("not kind of duration, can not convert")
   102  	}
   103  
   104  	num := time.Duration(q.Value)
   105  
   106  	switch q.Unit {
   107  	case NanoSecond:
   108  		return time.Nanosecond * num
   109  	case MicroSecond:
   110  		return time.Microsecond * num
   111  	case MilliSecond:
   112  		return time.Millisecond * num
   113  	case Second:
   114  		return time.Second * num
   115  	case Minute:
   116  		return time.Minute * num
   117  	case Hour:
   118  		return time.Hour * num
   119  	}
   120  	panic(fmt.Sprintf("not resolved duration unit: [%s]", q.Unit))
   121  }