func (q *Quantity) AsScale(scale Scale) (CanonicalValue, bool) {
	if q.d.Dec != nil {
		return q.d.AsScale(scale)
	}
	return q.i.AsScale(scale)
}
AsScale returns the current value, rounded up to the provided scale, and returns
false if the scale resulted in a loss of precision.
package resource
import (
	"bytes"
	"errors"
	"fmt"
	"math/big"
	"strconv"
	"strings"
	inf "gopkg.in/inf.v0"
)
type Quantity struct {
	i int64Amount
	d infDecAmount
	s string
	Format
}
type CanonicalValue interface {
	AsCanonicalBytes(out []byte) ([]byte, int32)
	AsCanonicalBase1024Bytes(out []byte) ([]byte, int32)
}
type Format string
const (
	DecimalExponent = Format("DecimalExponent")  
	BinarySI        = Format("BinarySI")         
	DecimalSI       = Format("DecimalSI")        
)
func MustParse(str string) Quantity {
	q, err := ParseQuantity(str)
	if err != nil {
		panic(fmt.Errorf("cannot parse '%v': %v", str, err))
	}
	return q
}
const (
	splitREString = "^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$"
)
var (
	ErrFormatWrong = errors.New("quantities must match the regular expression '" + splitREString + "'")
	ErrNumeric     = errors.New("unable to parse numeric part of quantity")
	ErrSuffix      = errors.New("unable to parse quantity's suffix")
)
func parseQuantityString(str string) (positive bool, value, num, denom, suffix string, err error) {
	positive = true
	pos := 0
	end := len(str)
	if pos < end {
		switch str[0] {
		case '-':
			positive = false
			pos++
		case '+':
			pos++
		}
	}
Zeroes:
	for i := pos; ; i++ {
		if i >= end {
			num = "0"
			value = num
			return
		}
		switch str[i] {
		case '0':
			pos++
		default:
			break Zeroes
		}
	}
Num:
	for i := pos; ; i++ {
		if i >= end {
			num = str[pos:end]
			value = str[0:end]
			return
		}
		switch str[i] {
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		default:
			num = str[pos:i]
			pos = i
			break Num
		}
	}
	if len(num) == 0 {
		num = "0"
	}
	if pos < end && str[pos] == '.' {
		pos++
	Denom:
		for i := pos; ; i++ {
			if i >= end {
				denom = str[pos:end]
				value = str[0:end]
				return
			}
			switch str[i] {
			case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
			default:
				denom = str[pos:i]
				pos = i
				break Denom
			}
		}
	}
	value = str[0:pos]
	suffixStart := pos
	for i := pos; ; i++ {
		if i >= end {
			suffix = str[suffixStart:end]
			return
		}
		if !strings.ContainsAny(str[i:i+1], "eEinumkKMGTP") {
			pos = i
			break
		}
	}
	if pos < end {
		switch str[pos] {
		case '-', '+':
			pos++
		}
	}
Suffix:
	for i := pos; ; i++ {
		if i >= end {
			suffix = str[suffixStart:end]
			return
		}
		switch str[i] {
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
		default:
			break Suffix
		}
	}
	err = ErrFormatWrong
	return
}
func ParseQuantity(str string) (Quantity, error) {
	if len(str) == 0 {
		return Quantity{}, ErrFormatWrong
	}
	if str == "0" {
		return Quantity{Format: DecimalSI, s: str}, nil
	}
	positive, value, num, denom, suf, err := parseQuantityString(str)
	if err != nil {
		return Quantity{}, err
	}
	base, exponent, format, ok := quantitySuffixer.interpret(suffix(suf))
	if !ok {
		return Quantity{}, ErrSuffix
	}
	precision := int32(0)
	scale := int32(0)
	mantissa := int64(1)
	switch format {
	case DecimalExponent, DecimalSI:
		scale = exponent
		precision = maxInt64Factors - int32(len(num)+len(denom))
	case BinarySI:
		scale = 0
		switch {
		case exponent >= 0 && len(denom) == 0:
			mantissa = int64(int64(mantissa) << uint64(exponent))
			precision = 15 - int32(len(num)) - int32(float32(exponent)*3/10) - 1
		default:
			precision = -1
		}
	}
	if precision >= 0 {
		scale -= int32(len(denom))
		if scale >= int32(Nano) {
			shifted := num + denom
			var value int64
			value, err := strconv.ParseInt(shifted, 10, 64)
			if err != nil {
				return Quantity{}, ErrNumeric
			}
			if result, ok := int64Multiply(value, int64(mantissa)); ok {
				if !positive {
					result = -result
				}
				switch format {
				case BinarySI:
					if exponent%10 == 0 && (value&0x07 != 0) {
						return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format, s: str}, nil
					}
				default:
					if scale%3 == 0 && !strings.HasSuffix(shifted, "000") && shifted[0] != '0' {
						return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format, s: str}, nil
					}
				}
				return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format}, nil
			}
		}
	}
	amount := new(inf.Dec)
	if _, ok := amount.SetString(value); !ok {
		return Quantity{}, ErrNumeric
	}
	if base == 10 {
		amount.SetScale(amount.Scale() + Scale(exponent).infScale())
	} else if base == 2 {
		numericSuffix := big.NewInt(1).Lsh(bigOne, uint(exponent))
		ub := amount.UnscaledBig()
		amount.SetUnscaledBig(ub.Mul(ub, numericSuffix))
	}
	sign := amount.Sign()
	if sign == -1 {
		amount.Neg(amount)
	}
	if v, ok := amount.Unscaled(); v != int64(0) || !ok {
		amount.Round(amount, Nano.infScale(), inf.RoundUp)
	}
	if format == BinarySI && amount.Cmp(maxAllowed.Dec) > 0 {
		amount.Set(maxAllowed.Dec)
	}
	if format == BinarySI && amount.Cmp(decOne) < 0 && amount.Cmp(decZero) > 0 {
		format = DecimalSI
	}
	if sign == -1 {
		amount.Neg(amount)
	}
	return Quantity{d: infDecAmount{amount}, Format: format}, nil
}
func (q Quantity) DeepCopy() Quantity {
	if q.d.Dec != nil {
		tmp := &inf.Dec{}
		q.d.Dec = tmp.Set(q.d.Dec)
	}
	return q
}
func (_ Quantity) OpenAPISchemaType() []string { return []string{"string"} }
func (_ Quantity) OpenAPISchemaFormat() string { return "" }
func (q *Quantity) CanonicalizeBytes(out []byte) (result, suffix []byte) {
	if q.IsZero() {
		return zeroBytes, nil
	}
	var rounded CanonicalValue
	format := q.Format
	switch format {
	case DecimalExponent, DecimalSI:
	case BinarySI:
		if q.CmpInt64(-1024) > 0 && q.CmpInt64(1024) < 0 {
			format = DecimalSI
		} else {
			var exact bool
			if rounded, exact = q.AsScale(0); !exact {
				format = DecimalSI
			}
		}
	default:
		format = DecimalExponent
	}
	switch format {
	case DecimalExponent, DecimalSI:
		number, exponent := q.AsCanonicalBytes(out)
		suffix, _ := quantitySuffixer.constructBytes(10, exponent, format)
		return number, suffix
	default:
		number, exponent := rounded.AsCanonicalBase1024Bytes(out)
		suffix, _ := quantitySuffixer.constructBytes(2, exponent*10, format)
		return number, suffix
	}
}
func (q *Quantity) AsInt64() (int64, bool) {
	if q.d.Dec != nil {
		return 0, false
	}
	return q.i.AsInt64()
}
func (q *Quantity) ToDec() *Quantity {
	if q.d.Dec == nil {
		q.d.Dec = q.i.AsDec()
		q.i = int64Amount{}
	}
	return q
}
func (q *Quantity) AsDec() *inf.Dec {
	if q.d.Dec != nil {
		return q.d.Dec
	}
	q.d.Dec = q.i.AsDec()
	q.i = int64Amount{}
	return q.d.Dec
}
func (q *Quantity) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
	if q.d.Dec != nil {
		return q.d.AsCanonicalBytes(out)
	}
	return q.i.AsCanonicalBytes(out)
}
func (q *Quantity) IsZero() bool {
	if q.d.Dec != nil {
		return q.d.Dec.Sign() == 0
	}
	return q.i.value == 0
}
func (q *Quantity) Sign() int {
	if q.d.Dec != nil {
		return q.d.Dec.Sign()
	}
	return q.i.Sign()
}