mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-25 01:44:43 +01:00
87 lines
1.5 KiB
Go
87 lines
1.5 KiB
Go
package datasizeunit
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Bits struct {
|
|
bits float64
|
|
}
|
|
|
|
func (b Bits) ToBits() float64 { return b.bits }
|
|
func (b Bits) ToBytes() float64 { return b.bits / 8 }
|
|
func FromBytesInt64(i int64) Bits { return Bits{float64(i) * 8} }
|
|
|
|
var datarateRegex = regexp.MustCompile(`^([-0-9\.]*)\s*(bit|(|K|Ki|M|Mi|G|Gi|T|Ti)([bB]))$`)
|
|
|
|
func (r *Bits) UnmarshalYAML(u func(interface{}, bool) error) (_ error) {
|
|
|
|
var s string
|
|
err := u(&s, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
genericErr := func(err error) error {
|
|
var buf strings.Builder
|
|
fmt.Fprintf(&buf, "cannot parse %q using regex %s", s, datarateRegex)
|
|
if err != nil {
|
|
fmt.Fprintf(&buf, ": %s", err)
|
|
}
|
|
return errors.New(buf.String())
|
|
}
|
|
|
|
match := datarateRegex.FindStringSubmatch(s)
|
|
if match == nil {
|
|
return genericErr(nil)
|
|
}
|
|
|
|
bps, err := strconv.ParseFloat(match[1], 64)
|
|
if err != nil {
|
|
return genericErr(err)
|
|
}
|
|
|
|
if match[2] == "bit" {
|
|
if math.Round(bps) != bps {
|
|
return genericErr(fmt.Errorf("unit bit must be an integer value"))
|
|
}
|
|
r.bits = bps
|
|
return nil
|
|
}
|
|
|
|
factorMap := map[string]uint64{
|
|
"": 1,
|
|
|
|
"K": 1e3,
|
|
"M": 1e6,
|
|
"G": 1e9,
|
|
"T": 1e12,
|
|
|
|
"Ki": 1 << 10,
|
|
"Mi": 1 << 20,
|
|
"Gi": 1 << 30,
|
|
"Ti": 1 << 40,
|
|
}
|
|
factor, ok := factorMap[match[3]]
|
|
if !ok {
|
|
panic(match)
|
|
}
|
|
|
|
baseUnitFactorMap := map[string]uint64{
|
|
"b": 1,
|
|
"B": 8,
|
|
}
|
|
baseUnitFactor, ok := baseUnitFactorMap[match[4]]
|
|
if !ok {
|
|
panic(match)
|
|
}
|
|
|
|
r.bits = bps * float64(factor) * float64(baseUnitFactor)
|
|
return nil
|
|
}
|