3
0

Define TypedValue comparators; Make parser init more flexible

This commit is contained in:
Tomaž Jerman
2021-05-30 14:50:02 +02:00
parent ddebcf6457
commit 98c16227b2
7 changed files with 241 additions and 6 deletions

View File

@@ -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 }}

View File

@@ -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

View 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
}
}

View File

@@ -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

View File

@@ -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'

View File

@@ -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) {

View File

@@ -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"`