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  }