-
Notifications
You must be signed in to change notification settings - Fork 0
/
params.go
71 lines (56 loc) · 1.33 KB
/
params.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package config
import (
"context"
"github.com/mitchellh/mapstructure"
"github.com/Azure/k6ctl/internal/target"
)
type paramsWithValidation interface {
Validate() error
}
type paramsWithDefaulting[T any] interface {
Defaulting(ctx context.Context, target target.Target) (T, error)
}
func applyDefaultingIfNeeded[T any](ctx context.Context, target target.Target, v T) (T, error) {
if withDefaulting, ok := (any(v)).(paramsWithDefaulting[T]); ok {
return withDefaulting.Defaulting(ctx, target)
}
return v, nil
}
func applyValidationIfNeeded(v any) error {
if withValidation, ok := v.(paramsWithValidation); ok {
return withValidation.Validate()
}
return nil
}
func withErr[T any](err error) (T, error) {
var empty T
return empty, err
}
// LoadForStruct loads the given user input map into the given struct and validates it.
func LoadForStruct[T any](
ctx context.Context,
target target.Target,
userInput map[string]any,
) (T, error) {
var (
rv T
err error
)
err = mapstructure.Decode(userInput, &rv)
if err != nil {
return withErr[T](err)
}
err = DefaultValidator.Struct(rv)
if err != nil {
return withErr[T](err)
}
rv, err = applyDefaultingIfNeeded(ctx, target, rv)
if err != nil {
return withErr[T](err)
}
err = applyValidationIfNeeded(rv)
if err != nil {
return withErr[T](err)
}
return rv, nil
}