Files
act_runner/internal/eval/v2/functions.go
Christopher Homberger 3413919161 update import path
2026-02-22 20:54:58 +01:00

203 lines
5.0 KiB
Go

package v2
import (
"encoding/json"
"errors"
"strings"
"gitea.com/gitea/act_runner/internal/eval/functions"
exprparser "gitea.com/gitea/act_runner/internal/expr"
)
type FromJSON struct {
}
func (FromJSON) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
r, err := eval.Evaluate(args[0])
if err != nil {
return nil, err
}
var res any
if err := json.Unmarshal([]byte(r.ConvertToString()), &res); err != nil {
return nil, err
}
return CreateIntermediateResult(eval.Context(), res), nil
}
type ToJSON struct {
}
func (ToJSON) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
r, err := eval.Evaluate(args[0])
if err != nil {
return nil, err
}
raw, err := eval.ToRaw(r)
if err != nil {
return nil, err
}
data, err := json.MarshalIndent(raw, "", " ")
if err != nil {
return nil, err
}
return CreateIntermediateResult(eval.Context(), string(data)), nil
}
type Contains struct {
}
func (Contains) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
collection, err := eval.Evaluate(args[0])
if err != nil {
return nil, err
}
el, err := eval.Evaluate(args[1])
if err != nil {
return nil, err
}
// Array
if col, ok := collection.TryGetCollectionInterface(); ok {
if node, ok := col.(ReadOnlyArray[any]); ok {
for _, v := range node.GetEnumerator() {
canon := CreateIntermediateResult(eval.Context(), v)
if canon.AbstractEqual(el) {
return CreateIntermediateResult(eval.Context(), true), nil
}
}
}
return CreateIntermediateResult(eval.Context(), false), nil
}
// String
return CreateIntermediateResult(eval.Context(), strings.Contains(strings.ToLower(collection.ConvertToString()), strings.ToLower(el.ConvertToString()))), nil
}
type StartsWith struct {
}
func (StartsWith) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
collection, err := eval.Evaluate(args[0])
if err != nil {
return nil, err
}
el, err := eval.Evaluate(args[1])
if err != nil {
return nil, err
}
// String
return CreateIntermediateResult(eval.Context(), strings.HasPrefix(strings.ToLower(collection.ConvertToString()), strings.ToLower(el.ConvertToString()))), nil
}
type EndsWith struct {
}
func (EndsWith) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
collection, err := eval.Evaluate(args[0])
if err != nil {
return nil, err
}
el, err := eval.Evaluate(args[1])
if err != nil {
return nil, err
}
// String
return CreateIntermediateResult(eval.Context(), strings.HasSuffix(strings.ToLower(collection.ConvertToString()), strings.ToLower(el.ConvertToString()))), nil
}
type Format struct {
}
func (Format) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
collection, err := eval.Evaluate(args[0])
if err != nil {
return nil, err
}
sargs := []interface{}{}
for _, arg := range args[1:] {
el, err := eval.Evaluate(arg)
if err != nil {
return nil, err
}
sargs = append(sargs, el.ConvertToString())
}
ret, err := functions.Format(collection.ConvertToString(), sargs...)
return CreateIntermediateResult(eval.Context(), ret), err
}
type Join struct {
}
func (Join) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
collection, err := eval.Evaluate(args[0])
if err != nil {
return nil, err
}
var el *EvaluationResult
if len(args) > 1 {
if el, err = eval.Evaluate(args[1]); err != nil {
return nil, err
}
}
// Array
if col, ok := collection.TryGetCollectionInterface(); ok {
var elements []string
if node, ok := col.(ReadOnlyArray[any]); ok {
for _, v := range node.GetEnumerator() {
elements = append(elements, CreateIntermediateResult(eval.Context(), v).ConvertToString())
}
}
var sep string
if el != nil {
sep = el.ConvertToString()
} else {
sep = ","
}
return CreateIntermediateResult(eval.Context(), strings.Join(elements, sep)), nil
}
// Primitive
if collection.IsPrimitive() {
return CreateIntermediateResult(eval.Context(), collection.ConvertToString()), nil
}
return CreateIntermediateResult(eval.Context(), ""), nil
}
type Case struct {
}
func (Case) Evaluate(eval *Evaluator, args []exprparser.Node) (*EvaluationResult, error) {
if len(args)%2 == 0 {
return nil, errors.New("case function requires an odd number of arguments")
}
for i := 0; i < len(args)-1; i += 2 {
condition, err := eval.Evaluate(args[i])
if err != nil {
return nil, err
}
if condition.kind != ValueKindBoolean {
return nil, errors.New("case function conditions must evaluate to boolean")
}
if condition.IsTruthy() {
return eval.Evaluate(args[i+1])
}
}
return eval.Evaluate(args[len(args)-1])
}
func GetFunctions() CaseInsensitiveObject[Function] {
return CaseInsensitiveObject[Function](map[string]Function{
"fromjson": &FromJSON{},
"tojson": &ToJSON{},
"contains": &Contains{},
"startswith": &StartsWith{},
"endswith": &EndsWith{},
"format": &Format{},
"join": &Join{},
"case": &Case{},
})
}