-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimple.go
101 lines (85 loc) · 2.47 KB
/
simple.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package myflags
import (
// "flag"
"fmt"
"reflect"
"strings"
flag "github.com/hujun-open/pflag"
)
func getTypeName(t reflect.Type) string {
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
return fmt.Sprint(t.PkgPath() + "=>" + t.String())
}
func getTypeNameForUsage(t reflect.Type) string {
if t.Kind() == reflect.Pointer {
t = t.Elem()
}
return t.String()
}
// FromStrFunc is a function convert string s into a specific type T, the tag is the struct field tag, as addtional input.
// see time.go for implementation examples
type FromStrFunc func(s string, tags reflect.StructTag) (any, error)
// ToStrFunc is a function convert in to string, the tag is the struct field tag, as addtional input.
// see time.go for implementation examples
type ToStrFunc func(in any, tags reflect.StructTag) string
type simpleType[T any] struct {
val *T
tags reflect.StructTag
fromStr FromStrFunc
toStr ToStrFunc
isBool bool
}
func newSimpleType[T any](from FromStrFunc, to ToStrFunc, tag reflect.StructTag, isbool bool) simpleType[T] {
return simpleType[T]{val: new(T), toStr: to, fromStr: from, tags: tag, isBool: isbool}
}
// implment flag.Value interface
func (v *simpleType[T]) String() string {
if v.val == nil {
return fmt.Sprint(nil)
}
return v.toStr(*v.val, v.tags)
}
// implment flag.Value interface
func (v *simpleType[T]) Set(s string) error {
r, err := v.fromStr(s, v.tags)
if err != nil {
return fmt.Errorf("failed to parse %s into %T, %w", s, *(new(T)), err)
}
// if v.val == nil {
// v.val = new(T)
// }
*v.val = r.(T)
return nil
}
// implment pflag.Value interface
func (v *simpleType[T]) Type() string {
return getTypeNameForUsage(reflect.TypeOf(v.val))
}
// implment flag.Value interface
func (v *simpleType[T]) IsBoolFlag() bool { return v.isBool }
type factory[T any] struct{}
func (f *factory[T]) process(fs *flag.FlagSet, ref reflect.Value, tag reflect.StructTag, name, short, usage string) {
// if ref.Type().Elem().Kind()
isbool := false
if reflect.TypeOf(*new(T)).Kind() == reflect.Bool {
isbool = true
}
casted := ref.Interface().(*T)
conv := globalRegistry.GetViaInterface(ref.Interface())
newval := newSimpleType[T](conv.FromStr, conv.ToStr, tag, isbool)
newval.SetRef(casted)
short = strings.TrimSpace(short)
// if strings.TrimSpace(short) == "" {
// fs.Var(&newval, name, usage)
// } else {
ff := fs.VarPF(&newval, name, short, usage)
if isbool {
ff.NoOptDefVal = "true"
}
// }
}
func (v *simpleType[T]) SetRef(t *T) {
v.val = t
}