github.com/Jeffail/benthos/v3@v3.65.0/public/bloblang/arguments.go (about) 1 package bloblang 2 3 import ( 4 "fmt" 5 "reflect" 6 7 "github.com/Jeffail/benthos/v3/internal/bloblang/query" 8 ) 9 10 // ArgSpec provides an API for validating and extracting function or method 11 // arguments by registering them with pointer receivers. 12 type ArgSpec struct { 13 n int 14 validators []func(args []interface{}) error 15 } 16 17 // NewArgSpec creates an argument parser/validator. 18 func NewArgSpec() *ArgSpec { 19 return &ArgSpec{} 20 } 21 22 // Extract the specified typed arguments from a slice of generic arguments. 23 // Returns an error if the number of arguments does not match the spec, and 24 // returns an *ArgError if the type of an argument is mismatched. 25 func (a *ArgSpec) Extract(args []interface{}) error { 26 if len(args) != a.n { 27 return fmt.Errorf("expected %v arguments, received %v", a.n, len(args)) 28 } 29 for _, v := range a.validators { 30 if err := v(args); err != nil { 31 return err 32 } 33 } 34 return nil 35 } 36 37 // IntVar creates an int argument to follow the previously created argument. 38 func (a *ArgSpec) IntVar(i *int) *ArgSpec { 39 index := a.n 40 a.n++ 41 42 a.validators = append(a.validators, func(args []interface{}) error { 43 v, err := query.IGetInt(args[index]) 44 if err != nil { 45 return newArgError(index, reflect.Int, args[index]) 46 } 47 *i = int(v) 48 return nil 49 }) 50 51 return a 52 } 53 54 // Int64Var creates an int64 argument to follow the previously created argument. 55 func (a *ArgSpec) Int64Var(i *int64) *ArgSpec { 56 index := a.n 57 a.n++ 58 59 a.validators = append(a.validators, func(args []interface{}) error { 60 v, err := query.IGetInt(args[index]) 61 if err != nil { 62 return newArgError(index, reflect.Int64, args[index]) 63 } 64 *i = v 65 return nil 66 }) 67 68 return a 69 } 70 71 // Float64Var creates a Float64 argument to follow the previously created 72 // argument. 73 func (a *ArgSpec) Float64Var(f *float64) *ArgSpec { 74 index := a.n 75 a.n++ 76 77 a.validators = append(a.validators, func(args []interface{}) error { 78 v, err := query.IGetNumber(args[index]) 79 if err != nil { 80 return newArgError(index, reflect.Float64, args[index]) 81 } 82 *f = v 83 return nil 84 }) 85 86 return a 87 } 88 89 // BoolVar creates a boolean argument to follow the previously created argument. 90 func (a *ArgSpec) BoolVar(b *bool) *ArgSpec { 91 index := a.n 92 a.n++ 93 94 a.validators = append(a.validators, func(args []interface{}) error { 95 v, err := query.IGetBool(args[index]) 96 if err != nil { 97 return newArgError(index, reflect.Bool, args[index]) 98 } 99 *b = v 100 return nil 101 }) 102 103 return a 104 } 105 106 // StringVar creates a string argument to follow the previously created 107 // argument. 108 func (a *ArgSpec) StringVar(s *string) *ArgSpec { 109 index := a.n 110 a.n++ 111 112 a.validators = append(a.validators, func(args []interface{}) error { 113 v, err := query.IGetString(args[index]) 114 if err != nil { 115 return newArgError(index, reflect.String, args[index]) 116 } 117 *s = v 118 return nil 119 }) 120 121 return a 122 } 123 124 // AnyVar creates an argument to follow the previously created argument that can 125 // have any value. 126 func (a *ArgSpec) AnyVar(i *interface{}) *ArgSpec { 127 index := a.n 128 a.n++ 129 130 a.validators = append(a.validators, func(args []interface{}) error { 131 *i = args[index] 132 return nil 133 }) 134 135 return a 136 } 137 138 //------------------------------------------------------------------------------ 139 140 // ArgError represents an error encountered when parsing a function or method 141 // argument. 142 type ArgError struct { 143 // The argument index 144 Index int 145 146 // The expected argument type 147 ExpectedKind reflect.Kind 148 149 // The actual type provided 150 ActualKind reflect.Kind 151 152 // The value of the argument 153 Value interface{} 154 } 155 156 func (a *ArgError) Error() string { 157 return fmt.Sprintf("bad argument %v: expected %v value, got %v (%v)", a.Index, a.ExpectedKind.String(), a.ActualKind.String(), a.Value) 158 } 159 160 func newArgError(index int, expected reflect.Kind, actual interface{}) error { 161 return &ArgError{ 162 Index: index, 163 ExpectedKind: expected, 164 ActualKind: reflect.TypeOf(actual).Kind(), 165 Value: actual, 166 } 167 }