github.com/kubeshop/testkube@v1.17.23/pkg/tcl/expressionstcl/machine.go (about) 1 // Copyright 2024 Testkube. 2 // 3 // Licensed as a Testkube Pro file under the Testkube Community 4 // License (the "License"); you may not use this file except in compliance with 5 // the License. You may obtain a copy of the License at 6 // 7 // https://github.com/kubeshop/testkube/blob/main/licenses/TCL.txt 8 9 package expressionstcl 10 11 import "strings" 12 13 //go:generate mockgen -destination=./mock_machine.go -package=expressionstcl "github.com/kubeshop/testkube/pkg/tcl/expressionstcl" Machine 14 type Machine interface { 15 Get(name string) (Expression, bool, error) 16 Call(name string, args ...StaticValue) (Expression, bool, error) 17 } 18 19 type MachineAccessorExt = func(name string) (interface{}, bool, error) 20 type MachineAccessor = func(name string) (interface{}, bool) 21 type MachineFn = func(values ...StaticValue) (interface{}, bool, error) 22 23 type machine struct { 24 accessors []MachineAccessorExt 25 functions map[string]MachineFn 26 } 27 28 func NewMachine() *machine { 29 return &machine{ 30 accessors: make([]MachineAccessorExt, 0), 31 functions: make(map[string]MachineFn), 32 } 33 } 34 35 func (m *machine) Register(name string, value interface{}) *machine { 36 return m.RegisterAccessor(func(n string) (interface{}, bool) { 37 if n == name { 38 return value, true 39 } 40 return nil, false 41 }) 42 } 43 44 func (m *machine) RegisterStringMap(prefix string, value map[string]string) *machine { 45 if len(prefix) > 0 { 46 prefix += "." 47 } 48 return m.RegisterAccessor(func(n string) (interface{}, bool) { 49 if !strings.HasPrefix(n, prefix) { 50 return nil, false 51 } 52 v, ok := value[n[len(prefix):]] 53 return v, ok 54 }) 55 } 56 57 func (m *machine) RegisterAccessorExt(fn MachineAccessorExt) *machine { 58 m.accessors = append(m.accessors, fn) 59 return m 60 } 61 62 func (m *machine) RegisterAccessor(fn MachineAccessor) *machine { 63 return m.RegisterAccessorExt(func(name string) (interface{}, bool, error) { 64 v, ok := fn(name) 65 return v, ok, nil 66 }) 67 } 68 69 func (m *machine) RegisterFunction(name string, fn MachineFn) *machine { 70 m.functions[name] = fn 71 return m 72 } 73 74 func (m *machine) Get(name string) (Expression, bool, error) { 75 for i := range m.accessors { 76 r, ok, err := m.accessors[i](name) 77 if err != nil { 78 return nil, true, err 79 } 80 if ok { 81 if v, ok := r.(Expression); ok { 82 return v, true, nil 83 } 84 return NewValue(r), true, nil 85 } 86 } 87 return nil, false, nil 88 } 89 90 func (m *machine) Call(name string, args ...StaticValue) (Expression, bool, error) { 91 fn, ok := m.functions[name] 92 if !ok { 93 return nil, false, nil 94 } 95 r, ok, err := fn(args...) 96 if !ok || err != nil { 97 return nil, ok, err 98 } 99 if v, ok := r.(Expression); ok { 100 return v, true, nil 101 } 102 return NewValue(r), true, nil 103 }