mirror of
https://github.com/kemko/nomad.git
synced 2026-01-05 18:05:42 +03:00
Units defined and parsing
This commit is contained in:
129
plugins/shared/structs/attribute.go
Normal file
129
plugins/shared/structs/attribute.go
Normal file
@@ -0,0 +1,129 @@
|
||||
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}
|
||||
}
|
||||
Reference in New Issue
Block a user