Files
higress/plugins/wasm-go/extensions/api-workflow/utils/conditional.go
2024-10-09 19:52:16 +08:00

117 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package utils
import (
"fmt"
"regexp"
"strconv"
"strings"
)
// 原子表达式描述:
// eq arg1 arg2: arg1 == arg2时为true
// ne arg1 arg2: arg1 != arg2时为true
// lt arg1 arg2: arg1 < arg2时为true
// le arg1 arg2: arg1 <= arg2时为true
// gt arg1 arg2: arg1 > arg2时为true
// ge arg1 arg2: arg1 >= arg2时为true
// and arg1 arg2: arg1 && arg2
// or arg1 arg2: arg1 || arg2
// contain arg1 arg2: arg1 包含 arg2时为true
var operators = map[string]interface{}{
"eq": func(a, b interface{}) bool {
return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b)
},
"ge": func(a, b float64) bool { return a >= b },
"le": func(a, b float64) bool { return a <= b },
"gt": func(a, b float64) bool { return a > b },
"lt": func(a, b float64) bool { return a < b },
"and": func(a, b bool) bool { return a && b },
"or": func(a, b bool) bool { return a || b },
"contain": func(a, b string) bool { return strings.Contains(a, b) },
}
// 执行判断条件
func ExecConditionalStr(conditionalStr string) (bool, error) {
// 正则表达式匹配括号内的表达式
re := regexp.MustCompile(`\(([^()]*)\)`)
matches := re.FindAllStringSubmatch(conditionalStr, -1)
// 找到最里面的(原子表达式)
for _, match := range matches {
subCondition := match[1]
result, err := ExecConditionalStr(subCondition)
if err != nil {
return false, err
}
// 用结果替换原子表达式
conditionalStr = strings.ReplaceAll(conditionalStr, match[0], fmt.Sprintf("%t", result))
}
fields := strings.Fields(conditionalStr)
// 执行原子表达式
if len(fields) == 3 {
compareFunc := operators[fields[0]]
switch fc := compareFunc.(type) {
default:
return false, fmt.Errorf("invalid conditional func %v", compareFunc)
case func(a, b float64) bool:
a, err := strconv.ParseFloat(fields[1], 64)
if err != nil {
return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
}
b, err := strconv.ParseFloat(fields[2], 64)
if err != nil {
return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
}
return fc(a, b), nil
case func(a, b bool) bool:
a, err := strconv.ParseBool(fields[1])
if err != nil {
return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
}
b, err := strconv.ParseBool(fields[2])
if err != nil {
return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
}
return fc(a, b), nil
case func(a, b string) bool:
a := fields[1]
b := fields[2]
return fc(a, b), nil
case func(a, b interface{}) bool:
a := fields[1]
b := fields[2]
return fc(a, b), nil
}
// 继续获取上一层的(原子表达式)
} else if strings.Contains(conditionalStr, "(") || strings.Contains(conditionalStr, ")") {
return ExecConditionalStr(conditionalStr)
// 原子表达式有问题,返回
} else {
return false, fmt.Errorf("invalid conditional str %s", conditionalStr)
}
}
// 通过正则表达式寻找模板中的 foo 字符串foo
// 返回 {{foo}} : foo
func ParseTmplStr(tmpl string) map[string]string {
result := make(map[string]string)
re := regexp.MustCompile(`\{\{(.*?)\}\}`)
matches := re.FindAllStringSubmatch(tmpl, -1)
for _, match := range matches {
result[match[0]] = match[1]
}
return result
}
// 使用kv替换模板中的字符
// 例如 模板是`hello,{{foo}}` 使用{"{{foo}}":"bot"} 替换后为`hello,bot`
func ReplacedStr(tmpl string, kvs map[string]string) string {
for k, v := range kvs {
tmpl = strings.Replace(tmpl, k, v, -1)
}
return tmpl
}