Define TypedValue comparators; Make parser init more flexible
This commit is contained in:
@@ -75,6 +75,33 @@ func (t *{{ $exprType }}) Assign(val interface{}) (error) {
|
||||
}
|
||||
}
|
||||
|
||||
{{ if $def.Comparable }}
|
||||
{{ if not $def.CustomComparator }}
|
||||
// Compare the two {{ $exprType }} values
|
||||
func (t {{ $exprType }}) Compare(to TypedValue) (int, error) {
|
||||
c, err := New{{ $exprType }}(to)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", t.Type(), c.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case t.value == c.value:
|
||||
return 0, nil
|
||||
case t.value < c.value:
|
||||
return -1, nil
|
||||
case t.value > c.value:
|
||||
return 1, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: unknown state", t.Type(), c.Type())
|
||||
}
|
||||
}
|
||||
{{ else }}
|
||||
// Compare the two {{ $exprType }} values
|
||||
func (t {{ $exprType }}) Compare(to TypedValue) (int, error) {
|
||||
return compareTo{{ $exprType }}(t, to)
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $def.Struct }}
|
||||
{{ if not $def.CustomFieldAssigner }}
|
||||
|
||||
@@ -2,10 +2,11 @@ package codegen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v3"
|
||||
"os"
|
||||
"path"
|
||||
"text/template"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -32,6 +33,8 @@ type (
|
||||
CustomGValSelector bool `yaml:"customGValSelector"`
|
||||
CustomSelector bool `yaml:"customSelector"`
|
||||
CustomFieldAssigner bool `yaml:"customFieldAssigner"`
|
||||
Comparable bool `yaml:"comparable"`
|
||||
CustomComparator bool `yaml:"customComparator"`
|
||||
Struct []*exprTypeStructDef
|
||||
|
||||
// @todo custom setters
|
||||
|
||||
56
pkg/expr/expr_type_comparators.go
Normal file
56
pkg/expr/expr_type_comparators.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func compareToBoolean(a Boolean, b TypedValue) (int, error) {
|
||||
c, err := NewBoolean(b)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", a.Type(), b.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case a.value == c.value:
|
||||
return 0, nil
|
||||
case !a.value && c.value:
|
||||
return -1, nil
|
||||
default:
|
||||
return 1, nil
|
||||
}
|
||||
}
|
||||
|
||||
func compareToDateTime(a DateTime, b TypedValue) (int, error) {
|
||||
c, err := NewDateTime(b)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", a.Type(), b.Type(), err.Error())
|
||||
}
|
||||
|
||||
ar := a.value.Nanosecond()
|
||||
cr := c.value.Nanosecond()
|
||||
|
||||
switch {
|
||||
case ar == cr:
|
||||
return 0, nil
|
||||
case ar < cr:
|
||||
return -1, nil
|
||||
default:
|
||||
return 1, nil
|
||||
}
|
||||
}
|
||||
|
||||
func compareToDuration(a Duration, b TypedValue) (int, error) {
|
||||
c, err := NewDuration(b)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", a.Type(), b.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case a.value == c.value:
|
||||
return 0, nil
|
||||
case a.value < c.value:
|
||||
return -1, nil
|
||||
default:
|
||||
return 1, nil
|
||||
}
|
||||
}
|
||||
129
pkg/expr/expr_types.gen.go
generated
129
pkg/expr/expr_types.gen.go
generated
@@ -166,6 +166,11 @@ func (t *Boolean) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two Boolean values
|
||||
func (t Boolean) Compare(to TypedValue) (int, error) {
|
||||
return compareToBoolean(t, to)
|
||||
}
|
||||
|
||||
// DateTime is an expression type, wrapper for *time.Time type
|
||||
type DateTime struct {
|
||||
value *time.Time
|
||||
@@ -215,6 +220,11 @@ func (t *DateTime) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two DateTime values
|
||||
func (t DateTime) Compare(to TypedValue) (int, error) {
|
||||
return compareToDateTime(t, to)
|
||||
}
|
||||
|
||||
// Duration is an expression type, wrapper for time.Duration type
|
||||
type Duration struct {
|
||||
value time.Duration
|
||||
@@ -264,6 +274,11 @@ func (t *Duration) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two Duration values
|
||||
func (t Duration) Compare(to TypedValue) (int, error) {
|
||||
return compareToDuration(t, to)
|
||||
}
|
||||
|
||||
// Float is an expression type, wrapper for float64 type
|
||||
type Float struct {
|
||||
value float64
|
||||
@@ -313,6 +328,25 @@ func (t *Float) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two Float values
|
||||
func (t Float) Compare(to TypedValue) (int, error) {
|
||||
c, err := NewFloat(to)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", t.Type(), c.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case t.value == c.value:
|
||||
return 0, nil
|
||||
case t.value < c.value:
|
||||
return -1, nil
|
||||
case t.value > c.value:
|
||||
return 1, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: unknown state", t.Type(), c.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// Handle is an expression type, wrapper for string type
|
||||
type Handle struct {
|
||||
value string
|
||||
@@ -362,6 +396,25 @@ func (t *Handle) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two Handle values
|
||||
func (t Handle) Compare(to TypedValue) (int, error) {
|
||||
c, err := NewHandle(to)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", t.Type(), c.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case t.value == c.value:
|
||||
return 0, nil
|
||||
case t.value < c.value:
|
||||
return -1, nil
|
||||
case t.value > c.value:
|
||||
return 1, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: unknown state", t.Type(), c.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// ID is an expression type, wrapper for uint64 type
|
||||
type ID struct {
|
||||
value uint64
|
||||
@@ -411,6 +464,25 @@ func (t *ID) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two ID values
|
||||
func (t ID) Compare(to TypedValue) (int, error) {
|
||||
c, err := NewID(to)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", t.Type(), c.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case t.value == c.value:
|
||||
return 0, nil
|
||||
case t.value < c.value:
|
||||
return -1, nil
|
||||
case t.value > c.value:
|
||||
return 1, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: unknown state", t.Type(), c.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// Integer is an expression type, wrapper for int64 type
|
||||
type Integer struct {
|
||||
value int64
|
||||
@@ -460,6 +532,25 @@ func (t *Integer) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two Integer values
|
||||
func (t Integer) Compare(to TypedValue) (int, error) {
|
||||
c, err := NewInteger(to)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", t.Type(), c.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case t.value == c.value:
|
||||
return 0, nil
|
||||
case t.value < c.value:
|
||||
return -1, nil
|
||||
case t.value > c.value:
|
||||
return 1, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: unknown state", t.Type(), c.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// KV is an expression type, wrapper for map[string]string type
|
||||
type KV struct {
|
||||
value map[string]string
|
||||
@@ -656,6 +747,25 @@ func (t *String) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two String values
|
||||
func (t String) Compare(to TypedValue) (int, error) {
|
||||
c, err := NewString(to)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", t.Type(), c.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case t.value == c.value:
|
||||
return 0, nil
|
||||
case t.value < c.value:
|
||||
return -1, nil
|
||||
case t.value > c.value:
|
||||
return 1, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: unknown state", t.Type(), c.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// UnsignedInteger is an expression type, wrapper for uint64 type
|
||||
type UnsignedInteger struct {
|
||||
value uint64
|
||||
@@ -705,6 +815,25 @@ func (t *UnsignedInteger) Assign(val interface{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two UnsignedInteger values
|
||||
func (t UnsignedInteger) Compare(to TypedValue) (int, error) {
|
||||
c, err := NewUnsignedInteger(to)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: %s", t.Type(), c.Type(), err.Error())
|
||||
}
|
||||
|
||||
switch {
|
||||
case t.value == c.value:
|
||||
return 0, nil
|
||||
case t.value < c.value:
|
||||
return -1, nil
|
||||
case t.value > c.value:
|
||||
return 1, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("cannot compare %s and %s: unknown state", t.Type(), c.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// Vars is an expression type, wrapper for map[string]TypedValue type
|
||||
type Vars struct {
|
||||
value map[string]TypedValue
|
||||
|
||||
@@ -16,37 +16,49 @@ types:
|
||||
Boolean:
|
||||
as: 'bool'
|
||||
default: 'false'
|
||||
comparable: true
|
||||
customComparator: true
|
||||
|
||||
ID:
|
||||
as: 'uint64'
|
||||
default: '0'
|
||||
comparable: true
|
||||
|
||||
Integer:
|
||||
as: 'int64'
|
||||
default: '0'
|
||||
comparable: true
|
||||
|
||||
UnsignedInteger:
|
||||
as: 'uint64'
|
||||
default: '0'
|
||||
comparable: true
|
||||
|
||||
Float:
|
||||
as: 'float64'
|
||||
default: '0'
|
||||
comparable: true
|
||||
|
||||
String:
|
||||
as: 'string'
|
||||
default: '""'
|
||||
comparable: true
|
||||
|
||||
Handle:
|
||||
as: 'string'
|
||||
default: '""'
|
||||
comparable: true
|
||||
|
||||
DateTime:
|
||||
as: '*time.Time'
|
||||
comparable: true
|
||||
customComparator: true
|
||||
|
||||
Duration:
|
||||
as: 'time.Duration'
|
||||
default: '0'
|
||||
comparable: true
|
||||
customComparator: true
|
||||
|
||||
KV:
|
||||
as: 'map[string]string'
|
||||
|
||||
@@ -32,12 +32,14 @@ type (
|
||||
}
|
||||
)
|
||||
|
||||
func NewParser() Parsable {
|
||||
return NewGvalParser()
|
||||
func NewParser(ee ...gval.Language) Parsable {
|
||||
return NewGvalParser(ee...)
|
||||
}
|
||||
|
||||
func NewGvalParser() *gvalParser {
|
||||
return &gvalParser{lang: gval.Full(AllFunctions()...)}
|
||||
func NewGvalParser(ee ...gval.Language) *gvalParser {
|
||||
ext := AllFunctions()
|
||||
ext = append(ext, ee...)
|
||||
return &gvalParser{lang: gval.Full(ext...)}
|
||||
}
|
||||
|
||||
func (p *gvalParser) Parse(expr string) (Evaluable, error) {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package expr
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type (
|
||||
Type interface {
|
||||
@@ -14,6 +16,10 @@ type (
|
||||
Get() interface{}
|
||||
}
|
||||
|
||||
Comparable interface {
|
||||
Compare(TypedValue) (int, error)
|
||||
}
|
||||
|
||||
typedValueWrap struct {
|
||||
Value interface{} `json:"@value"`
|
||||
Type string `json:"@type"`
|
||||
|
||||
Reference in New Issue
Block a user