checkSignature is an internal function for verifying a function signature matches the expected one. It is special in that it allows functions parameterised by one of the types, either input or output. You indicate the parameterised entry by having a nil for that type record, and the matching type is
(ctx context.Context, f reflect.Type, in []reflect.Type, out []reflect.Type)
| 34 | // returned from the fuction. |
| 35 | // It is an error to try to parameterise on more than one, behaviour is undefined in that case. |
| 36 | func checkSignature(ctx context.Context, f reflect.Type, in []reflect.Type, out []reflect.Type) (reflect.Type, error) { |
| 37 | if !(f.Kind() == reflect.Func) { |
| 38 | return nil, log.Errf(ctx, nil, "Expected a function. Got: %v", f) |
| 39 | } |
| 40 | if f.NumIn() != len(in) { |
| 41 | return nil, log.Errf(ctx, nil, "Invalid argument count: %d", f.NumIn()) |
| 42 | } |
| 43 | if f.NumOut() != len(out) { |
| 44 | return nil, log.Errf(ctx, nil, "Invalid return count: %v", f.NumOut()) |
| 45 | } |
| 46 | var res reflect.Type |
| 47 | for i, t := range in { |
| 48 | check := f.In(i) |
| 49 | if t == nil { |
| 50 | res = check |
| 51 | } else if check != t { |
| 52 | return nil, log.Errf(ctx, nil, "Incorrect parameter type: %v", check) |
| 53 | } |
| 54 | } |
| 55 | for i, t := range out { |
| 56 | check := f.Out(i) |
| 57 | if t == nil { |
| 58 | res = check |
| 59 | } else if check != t { |
| 60 | return nil, log.Errf(ctx, nil, "Incorrect return type: %v", check) |
| 61 | } |
| 62 | } |
| 63 | return res, nil |
| 64 | } |
| 65 | |
| 66 | func safeValue(v interface{}, t reflect.Type) reflect.Value { |
| 67 | if v == nil { |
no test coverage detected