3
0
corteza/pkg/expr/func_generic.go
2022-09-01 16:55:21 +02:00

129 lines
2.3 KiB
Go

package expr
import (
"fmt"
"reflect"
"github.com/PaesslerAG/gval"
"github.com/cortezaproject/corteza-server/pkg/gvalfnc"
)
type (
empty interface {
IsEmpty() bool
}
)
func GenericFunctions() []gval.Language {
return []gval.Language{
gval.Function("coalesce", coalesce),
gval.Function("isEmpty", isEmpty),
gval.Function("isNil", isNil),
gval.Function("length", length),
}
}
func coalesce(aa ...interface{}) interface{} {
for _, a := range aa {
if !isNil(a) {
return a
}
}
return nil
}
func length(i interface{}) int {
if isEmpty(i) {
return 0
}
switch reflect.TypeOf(i).Kind() {
case reflect.Slice, reflect.Array, reflect.Ptr, reflect.Map, reflect.String:
return reflect.ValueOf(i).Len()
}
return 0
}
func isNil(i interface{}) bool {
return gvalfnc.IsNil(i)
}
// empty checks values and slices
func isEmpty(i interface{}) bool {
if isNil(i) {
return true
}
if c, ok := i.(empty); ok {
return c.IsEmpty()
}
switch reflect.TypeOf(i).Kind() {
case reflect.Slice, reflect.Array, reflect.Map:
return reflect.ValueOf(i).Len() == 0
}
return reflect.ValueOf(i).IsZero()
}
func isInt(v interface{}) bool {
switch getKind(v) {
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint8:
return true
}
return false
}
func isString(v interface{}) bool {
return getKind(v) == reflect.String
}
func isFloat(v interface{}) bool {
switch getKind(v) {
case reflect.Float32, reflect.Float64:
return true
}
return false
}
func isBool(v interface{}) bool {
return getKind(v) == reflect.Bool
}
func getKind(v interface{}) reflect.Kind {
kind := reflect.TypeOf(v).Kind()
if isSlice(v) {
kind = reflect.TypeOf(v).Elem().Kind()
}
return kind
}
func isSlice(v interface{}) bool {
return reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array
}
func isMap(v interface{}) bool {
return reflect.TypeOf(v).Kind() == reflect.Map
}
// toArray removes expr types (if wrapped) and checks if the variable is slice
// internal only
//
//
func toSlice(vv interface{}) (interface{}, error) {
vv = UntypedValue(vv)
if !isSlice(vv) {
return nil, fmt.Errorf("unexpected type: %T, expecting slice", vv)
}
return vv, nil
}