aicra/typecheck/builtin/uint.go

71 lines
1.4 KiB
Go
Raw Permalink Normal View History

package builtin
import (
"encoding/json"
"math"
"git.xdrm.io/go/aicra/typecheck"
)
// Uint checks if a value is an uint
type Uint struct{}
// NewUint returns a bare number type checker
func NewUint() *Uint {
return &Uint{}
}
// Checker returns the checker function
func (Uint) Checker(typeName string) typecheck.CheckerFunc {
// nothing if type not handled
if typeName != "uint" {
return nil
}
return func(value interface{}) bool {
_, isInt := readUint(value)
return isInt
}
}
// readUint tries to read a serialized uint and returns whether it succeeded.
func readUint(value interface{}) (uint, bool) {
switch cast := value.(type) {
case int:
return uint(cast), cast >= 0
case uint:
return cast, true
case float64:
uintVal := uint(cast)
overflows := cast < 0 || cast > math.MaxUint64
return uintVal, cast == float64(uintVal) && !overflows
// serialized string -> try to convert to float
case string:
num := json.Number(cast)
floatVal, err := num.Float64()
if err != nil {
return 0, false
}
overflows := floatVal < 0 || floatVal > math.MaxUint64
return uint(floatVal), !overflows
case []byte:
num := json.Number(cast)
floatVal, err := num.Float64()
if err != nil {
return 0, false
}
overflows := floatVal < 0 || floatVal > math.MaxUint64
return uint(floatVal), !overflows
// unknown type
default:
return 0, false
}
}