src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/options.go (about) 1 package eval 2 3 import ( 4 "reflect" 5 6 "src.elv.sh/pkg/eval/vals" 7 "src.elv.sh/pkg/parse" 8 ) 9 10 // UnknownOption is thrown by a native function when called with an unknown option. 11 type UnknownOption struct { 12 OptName string 13 } 14 15 // Error implements the error interface. 16 func (e UnknownOption) Error() string { 17 return "unknown option: " + parse.Quote(e.OptName) 18 } 19 20 // RawOptions is the type of an argument a Go-native function can take to 21 // declare that it wants to parse options itself. See the doc of NewGoFn for 22 // details. 23 type RawOptions map[string]any 24 25 // Takes a raw option map and a pointer to a struct, and populate the struct 26 // with options. A field named FieldName corresponds to the option named 27 // field-name. Options that don't have corresponding fields in the struct causes 28 // an error. 29 // 30 // Similar to vals.ScanMapToGo, but requires rawOpts to contain a subset of keys 31 // supported by the struct. 32 func scanOptions(rawOpts RawOptions, ptr any) error { 33 _, keyIdx := vals.StructFieldsInfo(reflect.TypeOf(ptr).Elem()) 34 structValue := reflect.ValueOf(ptr).Elem() 35 for k, v := range rawOpts { 36 fieldIdx, ok := keyIdx[k] 37 if !ok { 38 return UnknownOption{k} 39 } 40 41 err := vals.ScanToGo(v, structValue.Field(fieldIdx).Addr().Interface()) 42 if err != nil { 43 return err 44 } 45 } 46 return nil 47 }