github.com/AlpineAIO/wails/v2@v2.0.0-beta.32.0.20240505041856-1047a8fa5fef/internal/binding/boundMethod.go (about) 1 package binding 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 ) 8 9 // BoundMethod defines all the data related to a Go method that is 10 // bound to the Wails application 11 type BoundMethod struct { 12 Name string `json:"name"` 13 Inputs []*Parameter `json:"inputs,omitempty"` 14 Outputs []*Parameter `json:"outputs,omitempty"` 15 Comments string `json:"comments,omitempty"` 16 Method reflect.Value `json:"-"` 17 } 18 19 // InputCount returns the number of inputs this bound method has 20 func (b *BoundMethod) InputCount() int { 21 return len(b.Inputs) 22 } 23 24 // OutputCount returns the number of outputs this bound method has 25 func (b *BoundMethod) OutputCount() int { 26 return len(b.Outputs) 27 } 28 29 // ParseArgs method converts the input json into the types expected by the method 30 func (b *BoundMethod) ParseArgs(args []json.RawMessage) ([]interface{}, error) { 31 result := make([]interface{}, b.InputCount()) 32 if len(args) != b.InputCount() { 33 return nil, fmt.Errorf("received %d arguments to method '%s', expected %d", len(args), b.Name, b.InputCount()) 34 } 35 for index, arg := range args { 36 typ := b.Inputs[index].reflectType 37 inputValue := reflect.New(typ).Interface() 38 err := json.Unmarshal(arg, inputValue) 39 if err != nil { 40 return nil, err 41 } 42 if inputValue == nil { 43 result[index] = reflect.Zero(typ).Interface() 44 } else { 45 result[index] = reflect.ValueOf(inputValue).Elem().Interface() 46 } 47 } 48 return result, nil 49 } 50 51 // Call will attempt to call this bound method with the given args 52 func (b *BoundMethod) Call(args []interface{}) (interface{}, error) { 53 // Check inputs 54 expectedInputLength := len(b.Inputs) 55 actualInputLength := len(args) 56 if expectedInputLength != actualInputLength { 57 return nil, fmt.Errorf("%s takes %d inputs. Received %d", b.Name, expectedInputLength, actualInputLength) 58 } 59 60 /** Convert inputs to reflect values **/ 61 62 // Create slice for the input arguments to the method call 63 callArgs := make([]reflect.Value, expectedInputLength) 64 65 // Iterate over given arguments 66 for index, arg := range args { 67 // Save the converted argument 68 callArgs[index] = reflect.ValueOf(arg) 69 } 70 71 // Do the call 72 callResults := b.Method.Call(callArgs) 73 74 //** Check results **// 75 var returnValue interface{} 76 var err error 77 78 switch b.OutputCount() { 79 case 1: 80 // Loop over results and determine if the result 81 // is an error or not 82 for _, result := range callResults { 83 interfac := result.Interface() 84 temp, ok := interfac.(error) 85 if ok { 86 err = temp 87 } else { 88 returnValue = interfac 89 } 90 } 91 case 2: 92 returnValue = callResults[0].Interface() 93 if temp, ok := callResults[1].Interface().(error); ok { 94 err = temp 95 } 96 } 97 98 return returnValue, err 99 }