diff --git a/CHANGELOG-0.3.md b/CHANGELOG-0.3.md index 2007e42..dba8d3f 100644 --- a/CHANGELOG-0.3.md +++ b/CHANGELOG-0.3.md @@ -1,4 +1,24 @@ -### v0.3.18 🌈 (2022-05-07 18:05:47) +### v0.3.21 🌈 (2022-06-20 18:05:10) + +#### 🤖 Tools + * 整理代码 ([ea167fb](https://github.com/sandwich-go/xconf/commit/ea167fbcded71a83df5b86a9918397f45677820f)) ([祝黄清](huangqing.zhu@centurygame.com)@2022-06-20 18:05:10 +0800 +0800) + * **sem**: make changelog ([1f3b253](https://github.com/sandwich-go/xconf/commit/1f3b253219899ca96487f767c471e7643cc4e3e0)) ([祝黄清](huangqing.zhu@centurygame.com)@2022-06-20 17:59:58 +0800 +0800) + +### v0.3.20 (2022-06-20 17:55:25) + +#### 🤖 Tools + * 增加MapStringUint64,MapUint64String,MapUint64Uint64的解析 ([bf1039c](https://github.com/sandwich-go/xconf/commit/bf1039c07998254d19dd0867f08413180c85e026)) ([祝黄清](huangqing.zhu@centurygame.com)@2022-06-20 17:55:25 +0800 +0800) + * **sem**: make changelog ([0d417ae](https://github.com/sandwich-go/xconf/commit/0d417ae04c428a2079706d11c4de224241b2d0f6)) ([Daming Yang](daming.yang@centurygame.com)@2022-05-10 16:48:49 +0800 +0800) + +### v0.3.19 (2022-05-10 16:46:00) + +#### 🛠 Refactor + * add error return value to ContentChange ([217843a](https://github.com/sandwich-go/xconf/commit/217843a2d2a9d583e12fc8843f347aaab01040e6)) ([Daming Yang](daming.yang@centurygame.com)@2022-05-10 16:46:00 +0800 +0800) + +#### 🤖 Tools + * **sem**: make changelog ([1352355](https://github.com/sandwich-go/xconf/commit/1352355546bc84b0bbbcea9fed700fe1588617ce)) ([hui.wang](hui.wang@funplus.com)@2022-05-07 18:06:04 +0800 +0800) + +### v0.3.18 (2022-05-07 18:05:47) #### 🐛 Bug Fixed * rm unused code ([e48f98a](https://github.com/sandwich-go/xconf/commit/e48f98a92fb92a5eea7a5718cc66fd63f81d5b08)) ([hui.wang](hui.wang@funplus.com)@2022-05-07 18:05:47 +0800 +0800) diff --git a/kv/loader.go b/kv/loader.go index 64dc33f..cdc7e3c 100644 --- a/kv/loader.go +++ b/kv/loader.go @@ -45,7 +45,7 @@ type Common struct { } // New 返回Common类型 -func New(name string, implement loaderImplement, opts ...Option) *Common { +func New(_ string, implement loaderImplement, opts ...Option) *Common { return &Common{implement: implement, fileMap: make(map[string]string), CC: NewOptions(opts...)} } @@ -101,13 +101,13 @@ func (c *Common) Watch(ctx context.Context, confPath string, onContentChange Con if c.CC.OnWatchError == nil { c.CC.OnWatchError = func(string, string, error) {} } - c.implement.WatchImplement(ctx, confPath, func(name string, confPath string, data []byte) { + c.implement.WatchImplement(ctx, confPath, func(name string, confPath string, data []byte) error { out, err := c.decode(data) if err == nil { - onContentChange(name, confPath, out) - return + return onContentChange(name, confPath, out) } c.CC.OnWatchError(name, confPath, fmt.Errorf("got error :%w while decode using secconf", err)) + return err }) } diff --git a/kv/option.go b/kv/option.go index 71781ac..8f5a78d 100644 --- a/kv/option.go +++ b/kv/option.go @@ -5,7 +5,7 @@ import ( ) // ContentChange kv数据发生变化时回调 -type ContentChange = func(loaderName string, confPath string, content []byte) +type ContentChange = func(loaderName string, confPath string, content []byte) error // WatchError kv.Loader.Watch发生错误时回调 type WatchError = func(loaderName string, confPath string, watchErr error) diff --git a/kv/xmem/mem.go b/kv/xmem/mem.go index 81612e1..3c1887c 100644 --- a/kv/xmem/mem.go +++ b/kv/xmem/mem.go @@ -24,10 +24,10 @@ func New(opts ...kv.Option) (p *Loader, err error) { } // CloseImplement 实现common.loaderImplement.CloseImplement -func (p *Loader) CloseImplement(ctx context.Context) error { return nil } +func (p *Loader) CloseImplement(_ context.Context) error { return nil } // GetImplement 实现common.loaderImplement.GetImplement -func (p *Loader) GetImplement(ctx context.Context, confPath string) ([]byte, error) { +func (p *Loader) GetImplement(_ context.Context, confPath string) ([]byte, error) { p.dataMutex.Lock() defer p.dataMutex.Unlock() v, ok := p.data[confPath] @@ -38,7 +38,7 @@ func (p *Loader) GetImplement(ctx context.Context, confPath string) ([]byte, err } // WatchImplement 实现common.loaderImplement.WatchImplement -func (p *Loader) WatchImplement(ctx context.Context, confPath string, onContentChange kv.ContentChange) { +func (p *Loader) WatchImplement(_ context.Context, confPath string, onContentChange kv.ContentChange) { p.dataMutex.Lock() defer p.dataMutex.Unlock() p.onChanged[confPath] = onContentChange @@ -53,7 +53,7 @@ func (p *Loader) Set(confPath string, data []byte) { return } p.data[confPath] = data - if f, ok := p.onChanged[confPath]; ok { - f(p.Name(), confPath, data) + if f, ok := p.onChanged[confPath]; ok && f != nil { + _ = f(p.Name(), confPath, data) } } diff --git a/tests/replit/config/gen_config_optiongen.go b/tests/replit/config/gen_config_optiongen.go index 9285d1d..c873393 100644 --- a/tests/replit/config/gen_config_optiongen.go +++ b/tests/replit/config/gen_config_optiongen.go @@ -518,46 +518,44 @@ func AtomicConfig() ConfigVisitor { } // all getter func -func (cc *Config) GetTypeBool() bool { return cc.TypeBool } -func (cc *Config) GetTypeString() string { return cc.TypeString } -func (cc *Config) GetTypeDuration() time.Duration { return cc.TypeDuration } -func (cc *Config) GetTypeFloat32() float32 { return cc.TypeFloat32 } -func (cc *Config) GetTypeFloat64() float32 { return cc.TypeFloat64 } -func (cc *Config) GetTypeInt() int { return cc.TypeInt } -func (cc *Config) GetTypeUint() int { return cc.TypeUint } -func (cc *Config) GetTypeInt8() int8 { return cc.TypeInt8 } -func (cc *Config) GetTypeUint8() uint8 { return cc.TypeUint8 } -func (cc *Config) GetTypeInt16() int16 { return cc.TypeInt16 } -func (cc *Config) GetTypeUint16() uint16 { return cc.TypeUint16 } -func (cc *Config) GetTypeInt32() int32 { return cc.TypeInt32 } -func (cc *Config) GetTypeUint32() uint32 { return cc.TypeUint32 } -func (cc *Config) GetTypeInt64() int64 { return cc.TypeInt64 } -func (cc *Config) GetTypeUint64() uint64 { return cc.TypeUint64 } -func (cc *Config) GetTypeSliceInt() []int { return cc.TypeSliceInt } -func (cc *Config) GetTypeSliceUint() []uint { return cc.TypeSliceUint } -func (cc *Config) GetTypeSliceInt8() []int8 { return cc.TypeSliceInt8 } -func (cc *Config) GetTypeSliceUint8() []uint8 { return cc.TypeSliceUint8 } -func (cc *Config) GetTypeSliceInt16() []int16 { return cc.TypeSliceInt16 } -func (cc *Config) GetTypeSliceUin16() []uint16 { return cc.TypeSliceUin16 } -func (cc *Config) GetTypeSliceInt32() []int32 { return cc.TypeSliceInt32 } -func (cc *Config) GetTypeSliceUint32() []uint32 { return cc.TypeSliceUint32 } -func (cc *Config) GetTypeSliceInt64() []int64 { return cc.TypeSliceInt64 } -func (cc *Config) GetTypeSliceUint64() []uint64 { return cc.TypeSliceUint64 } -func (cc *Config) GetTypeSliceString() []string { return cc.TypeSliceString } -func (cc *Config) GetTypeSliceFloat32() []float32 { return cc.TypeSliceFloat32 } -func (cc *Config) GetTypeSliceFloat64() []float64 { return cc.TypeSliceFloat64 } -func (cc *Config) GetTypeSliceDuratuon() []time.Duration { return cc.TypeSliceDuratuon } -func (cc *Config) GetTypeMapStringIntNotLeaf() map[string]int { return cc.TypeMapStringIntNotLeaf } -func (cc *Config) GetTypeMapStringInt() map[string]int { return cc.TypeMapStringInt } -func (cc *Config) GetTypeMapIntString() map[int]string { return cc.TypeMapIntString } -func (cc *Config) GetTypeMapStringString() map[string]string { return cc.TypeMapStringString } -func (cc *Config) GetTypeMapIntInt() map[int]int { return cc.TypeMapIntInt } -func (cc *Config) GetTypeMapStringDuration() map[string]time.Duration { - return cc.TypeMapStringDuration -} -func (cc *Config) GetRedis() RedisVisitor { return cc.Redis } -func (cc *Config) GetETCD() *ETCD { return cc.ETCD } -func (cc *Config) GetTestInterface() interface{} { return cc.TestInterface } +func (cc *Config) GetTypeBool() bool { return cc.TypeBool } +func (cc *Config) GetTypeString() string { return cc.TypeString } +func (cc *Config) GetTypeDuration() time.Duration { return cc.TypeDuration } +func (cc *Config) GetTypeFloat32() float32 { return cc.TypeFloat32 } +func (cc *Config) GetTypeFloat64() float32 { return cc.TypeFloat64 } +func (cc *Config) GetTypeInt() int { return cc.TypeInt } +func (cc *Config) GetTypeUint() int { return cc.TypeUint } +func (cc *Config) GetTypeInt8() int8 { return cc.TypeInt8 } +func (cc *Config) GetTypeUint8() uint8 { return cc.TypeUint8 } +func (cc *Config) GetTypeInt16() int16 { return cc.TypeInt16 } +func (cc *Config) GetTypeUint16() uint16 { return cc.TypeUint16 } +func (cc *Config) GetTypeInt32() int32 { return cc.TypeInt32 } +func (cc *Config) GetTypeUint32() uint32 { return cc.TypeUint32 } +func (cc *Config) GetTypeInt64() int64 { return cc.TypeInt64 } +func (cc *Config) GetTypeUint64() uint64 { return cc.TypeUint64 } +func (cc *Config) GetTypeSliceInt() []int { return cc.TypeSliceInt } +func (cc *Config) GetTypeSliceUint() []uint { return cc.TypeSliceUint } +func (cc *Config) GetTypeSliceInt8() []int8 { return cc.TypeSliceInt8 } +func (cc *Config) GetTypeSliceUint8() []uint8 { return cc.TypeSliceUint8 } +func (cc *Config) GetTypeSliceInt16() []int16 { return cc.TypeSliceInt16 } +func (cc *Config) GetTypeSliceUin16() []uint16 { return cc.TypeSliceUin16 } +func (cc *Config) GetTypeSliceInt32() []int32 { return cc.TypeSliceInt32 } +func (cc *Config) GetTypeSliceUint32() []uint32 { return cc.TypeSliceUint32 } +func (cc *Config) GetTypeSliceInt64() []int64 { return cc.TypeSliceInt64 } +func (cc *Config) GetTypeSliceUint64() []uint64 { return cc.TypeSliceUint64 } +func (cc *Config) GetTypeSliceString() []string { return cc.TypeSliceString } +func (cc *Config) GetTypeSliceFloat32() []float32 { return cc.TypeSliceFloat32 } +func (cc *Config) GetTypeSliceFloat64() []float64 { return cc.TypeSliceFloat64 } +func (cc *Config) GetTypeSliceDuratuon() []time.Duration { return cc.TypeSliceDuratuon } +func (cc *Config) GetTypeMapStringIntNotLeaf() map[string]int { return cc.TypeMapStringIntNotLeaf } +func (cc *Config) GetTypeMapStringInt() map[string]int { return cc.TypeMapStringInt } +func (cc *Config) GetTypeMapIntString() map[int]string { return cc.TypeMapIntString } +func (cc *Config) GetTypeMapStringString() map[string]string { return cc.TypeMapStringString } +func (cc *Config) GetTypeMapIntInt() map[int]int { return cc.TypeMapIntInt } +func (cc *Config) GetTypeMapStringDuration() map[string]time.Duration { return cc.TypeMapStringDuration } +func (cc *Config) GetRedis() RedisVisitor { return cc.Redis } +func (cc *Config) GetETCD() *ETCD { return cc.ETCD } +func (cc *Config) GetTestInterface() interface{} { return cc.TestInterface } // ConfigVisitor visitor interface for Config type ConfigVisitor interface { diff --git a/xcmd/gen_config_optiongen.go b/xcmd/gen_config_optiongen.go index b41105a..d7b23d0 100644 --- a/xcmd/gen_config_optiongen.go +++ b/xcmd/gen_config_optiongen.go @@ -3,12 +3,9 @@ package xcmd -import ( - "io" - "os" - - "github.com/sandwich-go/xconf" -) +import "io" +import "os" +import "github.com/sandwich-go/xconf" // config should use NewConfig to initialize it type config struct { diff --git a/xconf_remote.go b/xconf_remote.go index 44cbc49..bdabd18 100644 --- a/xconf_remote.go +++ b/xconf_remote.go @@ -66,7 +66,7 @@ func (x *XConf) notifyChanged() error { return nil } -func (x *XConf) onContentChanged(name string, confPath string, content []byte) { +func (x *XConf) onContentChanged(name string, confPath string, content []byte) (err error) { x.cc.LogDebug(fmt.Sprintf("got update:%s", confPath)) defer func() { if reason := recover(); reason == nil { @@ -77,10 +77,12 @@ func (x *XConf) onContentChanged(name string, confPath string, content []byte) { }() unmarshal := GetDecodeFunc(filepath.Ext(confPath)) data := make(map[string]interface{}) - err := unmarshal(content, data) + err = unmarshal(content, data) xutil.PanicErrWithWrap(err, "unmarshal_error(%v) ", err) xutil.PanicErr(x.commonUpdateAndNotify(func() error { - return x.mergeToDest(confPath, data) + err = x.mergeToDest(confPath, data) + return err })) + return } diff --git a/xflag/gen_options_optiongen.go b/xflag/gen_options_optiongen.go index 90e54ce..e83b65e 100644 --- a/xflag/gen_options_optiongen.go +++ b/xflag/gen_options_optiongen.go @@ -3,13 +3,10 @@ package xflag -import ( - "flag" - "log" - "strings" - - "github.com/sandwich-go/xconf/xflag/vars" -) +import "flag" +import "log" +import "strings" +import "github.com/sandwich-go/xconf/xflag/vars" // Options should use NewOptions to initialize it type Options struct { diff --git a/xflag/vars/gen.go b/xflag/vars/gen.go index 440d7e5..eecc4f5 100644 --- a/xflag/vars/gen.go +++ b/xflag/vars/gen.go @@ -121,4 +121,8 @@ func parseBool(s string) (bool, error) { return strconv.ParseBool(s) } //go:generate gotemplate -outfmt gen_%v "../templates/xmap" "MapInt64String(int64,string,parseInt64,parseString,SetProviderByFieldType,StringValueDelim)" //go:generate gotemplate -outfmt gen_%v "../templates/xmap" "MapInt64Int64(int64,int64,parseInt64,parseInt64,SetProviderByFieldType,StringValueDelim)" +//go:generate gotemplate -outfmt gen_%v "../templates/xmap" "MapStringUint64(string,uint64,parseString,parseUint64,SetProviderByFieldType,StringValueDelim)" +//go:generate gotemplate -outfmt gen_%v "../templates/xmap" "MapUint64String(uint64,string,parseUint64,parseString,SetProviderByFieldType,StringValueDelim)" +//go:generate gotemplate -outfmt gen_%v "../templates/xmap" "MapUint64Uint64(uint64,uint64,parseUint64,parseUint64,SetProviderByFieldType,StringValueDelim)" + //go:generate gotemplate -outfmt gen_%v "../templates/xmap" "MapStringTimeDuration(string,time.Duration,parseString,parseTimeDuration,SetProviderByFieldType,StringValueDelim)" diff --git a/xflag/vars/gen_MapStringUint64.go b/xflag/vars/gen_MapStringUint64.go new file mode 100644 index 0000000..711288a --- /dev/null +++ b/xflag/vars/gen_MapStringUint64.go @@ -0,0 +1,113 @@ +// Code generated by gotemplate. DO NOT EDIT. + +package vars + +import ( + "errors" + "flag" + "fmt" + "reflect" + "strings" +) + +//template type MapKTypeVType(KType,VType,ParseKeyFunc,ParseValFunc,SetProviderByFieldType,StringValueDelim) + +// KType 默认key类型 + +// VType 默认val类型 + +// StringValueDelim 数据分割符 + +// SetProviderByFieldType 替换 + +// ParseKeyFunc key解析,替换 + +// ParseValFunc val解析,替换 + +var typeNameMapStringUint64 = "" + +func init() { + v := map[string]uint64{} + typeNameMapStringUint64 = fmt.Sprintf("map[%s]%s", reflect.TypeOf(v).Key().Name(), reflect.TypeOf(v).Elem().Name()) + SetProviderByFieldType(typeNameMapStringUint64, func(valPtr interface{}, stringAlias func(s string) string) flag.Getter { + return NewMapStringUint64(valPtr, stringAlias) + }) +} + +// MapKTypeVType new func +type MapStringUint64 struct { + stringAlias func(s string) string + s string + set bool + val *map[string]uint64 +} + +// NewMapKTypeVType 创建指定类型 +func NewMapStringUint64(valPtr interface{}, stringAlias func(s string) string) *MapStringUint64 { + return &MapStringUint64{ + val: valPtr.(*map[string]uint64), + stringAlias: stringAlias, + } +} + +// Get 返回数据,必须返回map[string]interface{}类型 +func (e *MapStringUint64) Get() interface{} { + vv := make(map[string]interface{}) + for k, v := range *e.val { + vv[fmt.Sprintf("%v", k)] = v + } + return vv +} + +// Usage usage info for FlagSet +func (e *MapStringUint64) Usage() string { + return fmt.Sprintf("xconf/xflag/vars, key and value split by %s", StringValueDelim) +} + +// TypeName type name for vars FlagValue provider +func (e *MapStringUint64) TypeName() string { return typeNameMapStringUint64 } + +// String 获取Set设置的字符串数据?或数据转换到的? +func (e *MapStringUint64) String() string { + if e.val == nil || len(*e.val) == 0 { + return "" + } + return fmt.Sprintf("%v", *e.val) +} + +// Set 解析时由FlagSet设定而来,进行解析 +func (e *MapStringUint64) Set(s string) error { + s = e.stringAlias(s) + e.s = s + kv := strings.Split(s, StringValueDelim) + if len(kv)%2 == 1 { + // 设定了default标签或者空的字符串 + if len(kv) == 1 && kv[0] == "" { + return nil + } + return errors.New("got the odd number of input pairs") + } + if !e.set { + e.set = true + *e.val = make(map[string]uint64) + } + var key string + for i, val := range kv { + if i%2 == 0 { + key = val + continue + } + keyAlias := e.stringAlias(key) + keyVal, err := parseString(keyAlias) + if err != nil { + return fmt.Errorf("got err:%s while parse key:%s alias:%s raw:%s", err.Error(), key, keyAlias, s) + } + valAlias := e.stringAlias(val) + valVal, err := parseUint64(valAlias) + if err != nil { + return fmt.Errorf("got err:%s while parse val:%s alias:%s raw:%s", err.Error(), val, valAlias, s) + } + (*e.val)[keyVal] = valVal + } + return nil +} diff --git a/xflag/vars/gen_MapUint64String.go b/xflag/vars/gen_MapUint64String.go new file mode 100644 index 0000000..8d971a9 --- /dev/null +++ b/xflag/vars/gen_MapUint64String.go @@ -0,0 +1,113 @@ +// Code generated by gotemplate. DO NOT EDIT. + +package vars + +import ( + "errors" + "flag" + "fmt" + "reflect" + "strings" +) + +//template type MapKTypeVType(KType,VType,ParseKeyFunc,ParseValFunc,SetProviderByFieldType,StringValueDelim) + +// KType 默认key类型 + +// VType 默认val类型 + +// StringValueDelim 数据分割符 + +// SetProviderByFieldType 替换 + +// ParseKeyFunc key解析,替换 + +// ParseValFunc val解析,替换 + +var typeNameMapUint64String = "" + +func init() { + v := map[uint64]string{} + typeNameMapUint64String = fmt.Sprintf("map[%s]%s", reflect.TypeOf(v).Key().Name(), reflect.TypeOf(v).Elem().Name()) + SetProviderByFieldType(typeNameMapUint64String, func(valPtr interface{}, stringAlias func(s string) string) flag.Getter { + return NewMapUint64String(valPtr, stringAlias) + }) +} + +// MapKTypeVType new func +type MapUint64String struct { + stringAlias func(s string) string + s string + set bool + val *map[uint64]string +} + +// NewMapKTypeVType 创建指定类型 +func NewMapUint64String(valPtr interface{}, stringAlias func(s string) string) *MapUint64String { + return &MapUint64String{ + val: valPtr.(*map[uint64]string), + stringAlias: stringAlias, + } +} + +// Get 返回数据,必须返回map[string]interface{}类型 +func (e *MapUint64String) Get() interface{} { + vv := make(map[string]interface{}) + for k, v := range *e.val { + vv[fmt.Sprintf("%v", k)] = v + } + return vv +} + +// Usage usage info for FlagSet +func (e *MapUint64String) Usage() string { + return fmt.Sprintf("xconf/xflag/vars, key and value split by %s", StringValueDelim) +} + +// TypeName type name for vars FlagValue provider +func (e *MapUint64String) TypeName() string { return typeNameMapUint64String } + +// String 获取Set设置的字符串数据?或数据转换到的? +func (e *MapUint64String) String() string { + if e.val == nil || len(*e.val) == 0 { + return "" + } + return fmt.Sprintf("%v", *e.val) +} + +// Set 解析时由FlagSet设定而来,进行解析 +func (e *MapUint64String) Set(s string) error { + s = e.stringAlias(s) + e.s = s + kv := strings.Split(s, StringValueDelim) + if len(kv)%2 == 1 { + // 设定了default标签或者空的字符串 + if len(kv) == 1 && kv[0] == "" { + return nil + } + return errors.New("got the odd number of input pairs") + } + if !e.set { + e.set = true + *e.val = make(map[uint64]string) + } + var key string + for i, val := range kv { + if i%2 == 0 { + key = val + continue + } + keyAlias := e.stringAlias(key) + keyVal, err := parseUint64(keyAlias) + if err != nil { + return fmt.Errorf("got err:%s while parse key:%s alias:%s raw:%s", err.Error(), key, keyAlias, s) + } + valAlias := e.stringAlias(val) + valVal, err := parseString(valAlias) + if err != nil { + return fmt.Errorf("got err:%s while parse val:%s alias:%s raw:%s", err.Error(), val, valAlias, s) + } + (*e.val)[keyVal] = valVal + } + return nil +} diff --git a/xflag/vars/gen_MapUint64Uint64.go b/xflag/vars/gen_MapUint64Uint64.go new file mode 100644 index 0000000..ff14691 --- /dev/null +++ b/xflag/vars/gen_MapUint64Uint64.go @@ -0,0 +1,113 @@ +// Code generated by gotemplate. DO NOT EDIT. + +package vars + +import ( + "errors" + "flag" + "fmt" + "reflect" + "strings" +) + +//template type MapKTypeVType(KType,VType,ParseKeyFunc,ParseValFunc,SetProviderByFieldType,StringValueDelim) + +// KType 默认key类型 + +// VType 默认val类型 + +// StringValueDelim 数据分割符 + +// SetProviderByFieldType 替换 + +// ParseKeyFunc key解析,替换 + +// ParseValFunc val解析,替换 + +var typeNameMapUint64Uint64 = "" + +func init() { + v := map[uint64]uint64{} + typeNameMapUint64Uint64 = fmt.Sprintf("map[%s]%s", reflect.TypeOf(v).Key().Name(), reflect.TypeOf(v).Elem().Name()) + SetProviderByFieldType(typeNameMapUint64Uint64, func(valPtr interface{}, stringAlias func(s string) string) flag.Getter { + return NewMapUint64Uint64(valPtr, stringAlias) + }) +} + +// MapKTypeVType new func +type MapUint64Uint64 struct { + stringAlias func(s string) string + s string + set bool + val *map[uint64]uint64 +} + +// NewMapKTypeVType 创建指定类型 +func NewMapUint64Uint64(valPtr interface{}, stringAlias func(s string) string) *MapUint64Uint64 { + return &MapUint64Uint64{ + val: valPtr.(*map[uint64]uint64), + stringAlias: stringAlias, + } +} + +// Get 返回数据,必须返回map[string]interface{}类型 +func (e *MapUint64Uint64) Get() interface{} { + vv := make(map[string]interface{}) + for k, v := range *e.val { + vv[fmt.Sprintf("%v", k)] = v + } + return vv +} + +// Usage usage info for FlagSet +func (e *MapUint64Uint64) Usage() string { + return fmt.Sprintf("xconf/xflag/vars, key and value split by %s", StringValueDelim) +} + +// TypeName type name for vars FlagValue provider +func (e *MapUint64Uint64) TypeName() string { return typeNameMapUint64Uint64 } + +// String 获取Set设置的字符串数据?或数据转换到的? +func (e *MapUint64Uint64) String() string { + if e.val == nil || len(*e.val) == 0 { + return "" + } + return fmt.Sprintf("%v", *e.val) +} + +// Set 解析时由FlagSet设定而来,进行解析 +func (e *MapUint64Uint64) Set(s string) error { + s = e.stringAlias(s) + e.s = s + kv := strings.Split(s, StringValueDelim) + if len(kv)%2 == 1 { + // 设定了default标签或者空的字符串 + if len(kv) == 1 && kv[0] == "" { + return nil + } + return errors.New("got the odd number of input pairs") + } + if !e.set { + e.set = true + *e.val = make(map[uint64]uint64) + } + var key string + for i, val := range kv { + if i%2 == 0 { + key = val + continue + } + keyAlias := e.stringAlias(key) + keyVal, err := parseUint64(keyAlias) + if err != nil { + return fmt.Errorf("got err:%s while parse key:%s alias:%s raw:%s", err.Error(), key, keyAlias, s) + } + valAlias := e.stringAlias(val) + valVal, err := parseUint64(valAlias) + if err != nil { + return fmt.Errorf("got err:%s while parse val:%s alias:%s raw:%s", err.Error(), val, valAlias, s) + } + (*e.val)[keyVal] = valVal + } + return nil +}