mirror of
https://github.com/kemko/nomad.git
synced 2026-01-02 00:15:43 +03:00
130 lines
2.9 KiB
Go
130 lines
2.9 KiB
Go
package structs
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
)
|
|
|
|
// BaseUnit is a unique base unit. All units that share the same base unit
|
|
// should be comparable.
|
|
type BaseUnit uint16
|
|
|
|
const (
|
|
UnitScalar BaseUnit = iota
|
|
UnitByte
|
|
UnitByteRate
|
|
UnitHertz
|
|
UnitWatt
|
|
)
|
|
|
|
// Unit describes a unit and its multiplier over the base unit type
|
|
type Unit struct {
|
|
// Name is the name of the unit (GiB, MB/s)
|
|
Name string
|
|
|
|
// Base is the base unit for the unit
|
|
Base BaseUnit
|
|
|
|
// Multiplier is the multiplier over the base unit (KiB multiplier is 1024)
|
|
Multiplier uint64
|
|
|
|
// InverseMultiplier specifies that the multiplier is an inverse so:
|
|
// Base / Multiplier. For example a mW is a W/1000.
|
|
InverseMultiplier bool
|
|
}
|
|
|
|
// Comparable returns if two units are comparable
|
|
func (u *Unit) Comparable(o *Unit) bool {
|
|
if u == nil || o == nil {
|
|
return false
|
|
}
|
|
|
|
return u.Base == o.Base
|
|
}
|
|
|
|
// Attribute is used to describe the value of an attribute, optionally
|
|
// specifying units
|
|
type Attribute struct {
|
|
// Float is the float value for the attribute
|
|
Float float64
|
|
|
|
// Int is the int value for the attribute
|
|
Int int64
|
|
|
|
// String is the string value for the attribute
|
|
String string
|
|
|
|
// Bool is the bool value for the attribute
|
|
Bool bool
|
|
|
|
// Unit is the optional unit for the set int or float value
|
|
Unit string
|
|
}
|
|
|
|
// Validate checks if the attribute is valid
|
|
func (a *Attribute) Validate() error {
|
|
if a.Unit != "" {
|
|
if _, ok := UnitIndex[a.Unit]; !ok {
|
|
return fmt.Errorf("unrecognized unit %q", a.Unit)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
// numericWithUnits matches only if it is a integer or float ending with
|
|
// units. It has two capture groups, one for the numeric value and one for
|
|
// the unit value
|
|
numericWithUnits = regexp.MustCompile(`^([-]?(?:[0-9]+|[0-9]+\.[0-9]+|\.[0-9]+))\s*([a-zA-Z]+\/?[a-zA-z]+|[a-zA-Z])$`)
|
|
)
|
|
|
|
func ParseAttribute(input string) *Attribute {
|
|
// Try to parse as a bool
|
|
b, err := strconv.ParseBool(input)
|
|
if err == nil {
|
|
return &Attribute{Bool: b}
|
|
}
|
|
|
|
// Try to parse as a number.
|
|
|
|
// Check if the string is a number ending with potential units
|
|
if matches := numericWithUnits.FindStringSubmatch(input); len(matches) == 3 {
|
|
numeric := matches[1]
|
|
unit := matches[2]
|
|
|
|
// Check if we know about the unit. If we don't we can only treat this
|
|
// as a string
|
|
if _, ok := UnitIndex[unit]; !ok {
|
|
return &Attribute{String: input}
|
|
}
|
|
|
|
// Try to parse as an int
|
|
i, err := strconv.ParseInt(numeric, 10, 64)
|
|
if err == nil {
|
|
return &Attribute{Int: i, Unit: unit}
|
|
}
|
|
|
|
// Try to parse as a float
|
|
f, err := strconv.ParseFloat(numeric, 64)
|
|
if err == nil {
|
|
return &Attribute{Float: f, Unit: unit}
|
|
}
|
|
}
|
|
|
|
// Try to parse as an int
|
|
i, err := strconv.ParseInt(input, 10, 64)
|
|
if err == nil {
|
|
return &Attribute{Int: i}
|
|
}
|
|
|
|
// Try to parse as a float
|
|
f, err := strconv.ParseFloat(input, 64)
|
|
if err == nil {
|
|
return &Attribute{Float: f}
|
|
}
|
|
|
|
return &Attribute{String: input}
|
|
}
|