diff --git a/go.mod b/go.mod index 2d458e658a..0b3b003bf4 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/go-tika v0.3.0 github.com/google/uuid v1.5.0 - github.com/gookit/config/v2 v2.2.4 + github.com/gookit/config/v2 v2.2.5 github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 github.com/jellydator/ttlcache/v2 v2.11.1 @@ -223,7 +223,7 @@ require ( github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/renameio/v2 v2.0.0 // indirect github.com/gookit/color v1.5.4 // indirect - github.com/gookit/goutil v0.6.14 // indirect + github.com/gookit/goutil v0.6.15 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/schema v1.2.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect diff --git a/go.sum b/go.sum index a2d73cb7d0..2a8e210ab5 100644 --- a/go.sum +++ b/go.sum @@ -1423,12 +1423,12 @@ github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= -github.com/gookit/config/v2 v2.2.4 h1:uLHNzFzREe5gDBP4Gb1+WOC9LB6vauPvq4eolp32Dcg= -github.com/gookit/config/v2 v2.2.4/go.mod h1:k1ofSAuJnW6n1kTriFMSzFDC8ZT20tAPQ+1iGI3QOrU= -github.com/gookit/goutil v0.6.14 h1:96elyOG4BvVoDaiT7vx1vHPrVyEtFfYlPPBODR0/FGQ= -github.com/gookit/goutil v0.6.14/go.mod h1:YyDBddefmjS+mU2PDPgCcjVzTDM5WgExiDv5ZA/b8I8= -github.com/gookit/ini/v2 v2.2.2 h1:3B8abZJrVH1vi/7TU4STuTBxdhiAq1ORSt6NJZCahaI= -github.com/gookit/ini/v2 v2.2.2/go.mod h1:wGEfnBxv+7nVXytWM44tiqczv5hLKJ+m9MaA2uJg3iM= +github.com/gookit/config/v2 v2.2.5 h1:RECbYYbtherywmzn3LNeu9NA5ZqhD7MSKEMsJ7l+MpU= +github.com/gookit/config/v2 v2.2.5/go.mod h1:NeX+yiNYn6Ei10eJvCQFXuHEPIE/IPS8bqaFIsszzaM= +github.com/gookit/goutil v0.6.15 h1:mMQ0ElojNZoyPD0eVROk5QXJPh2uKR4g06slgPDF5Jo= +github.com/gookit/goutil v0.6.15/go.mod h1:qdKdYEHQdEtyH+4fNdQNZfJHhI0jUZzHxQVAV3DaMDY= +github.com/gookit/ini/v2 v2.2.3 h1:nSbN+x9OfQPcMObTFP+XuHt8ev6ndv/fWWqxFhPMu2E= +github.com/gookit/ini/v2 v2.2.3/go.mod h1:Vu6p7P7xcfmb8KYu3L0ek8bqu/Im63N81q208SCCZY4= github.com/gophercloud/gophercloud v0.15.1-0.20210202035223-633d73521055/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= github.com/gophercloud/gophercloud v0.16.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae/go.mod h1:wx8HMD8oQD0Ryhz6+6ykq75PJ79iPyEqYHfwZ4l7OsA= diff --git a/vendor/github.com/gookit/config/v2/README.md b/vendor/github.com/gookit/config/v2/README.md index 908385d625..70e9bbc261 100644 --- a/vendor/github.com/gookit/config/v2/README.md +++ b/vendor/github.com/gookit/config/v2/README.md @@ -89,6 +89,7 @@ import ( // go run ./examples/yaml.go func main() { + // config.ParseEnv: will parse env var in string value. eg: shell: ${SHELL} config.WithOptions(config.ParseEnv) // add driver for support yaml content @@ -350,7 +351,7 @@ ioutil.WriteFile("my-config.yaml", buf.Bytes(), 0755) ```go // Options config options type Options struct { - // parse env value. like: "${EnvName}" "${EnvName|default}" + // parse env in string value. like: "${EnvName}" "${EnvName|default}" ParseEnv bool // ParseTime parses a duration string to time.Duration // eg: 10s, 2m @@ -361,10 +362,6 @@ type Options struct { EnableCache bool // parse key, allow find value by key path. default is True eg: 'key.sub' will find `map[key]sub` ParseKey bool - // tag name for binding data to struct - // Deprecated - // please set tag name by DecoderConfig - TagName string // the delimiter char for split key path, if `FindByPath=true`. default is '.' Delimiter byte // default write format @@ -380,6 +377,15 @@ type Options struct { } ``` +Examples for set options: + +```go +config.WithOptions(config.WithTagName("mytag")) +config.WithOptions(func(opt *Options) { + opt.SetTagNames("config") +}) +``` + ### Options: Parse default Support parse default value by struct tag `default` diff --git a/vendor/github.com/gookit/config/v2/README.zh-CN.md b/vendor/github.com/gookit/config/v2/README.zh-CN.md index 077e8046d7..7b161dda40 100644 --- a/vendor/github.com/gookit/config/v2/README.zh-CN.md +++ b/vendor/github.com/gookit/config/v2/README.zh-CN.md @@ -21,14 +21,20 @@ - 支持从 OS ENV 变量数据加载配置 - 支持从远程 URL 加载配置数据 - 支持从命令行参数(`flags`)设置配置数据 -- 支持在配置数据更改时触发事件 - - 可用事件: `set.value`, `set.data`, `load.data`, `clean.data`, `reload.data` -- 支持数据覆盖合并,加载多份数据时将按key自动合并 +- 数据自动覆盖合并,加载多份数据时将按`key`自动合并 +- 支持丰富的自定义选项设置 + - `Readonly` 支持设置配置数据只读 + - `EnableCache` 支持设置配置数据缓存 + - `ParseEnv` 支持获取时自动解析string值里的ENV变量(`shell: ${SHELL}` -> `shell: /bin/zsh`) + - `ParseDefault` 支持在绑定数据到结构体时解析默认值 (tag: `default:"def_value"`, 配合ParseEnv也支持ENV变量) + - `ParseTime` 支持绑定数据到struct时自动转换 `10s`,`2m` 为 `time.Duration` + - 完整选项设置请查看 `config.Options` - 支持将全部或部分配置数据绑定到结构体 `config.BindStruct("key", &s)` - 支持通过结构体标签 `default` 解析并设置默认值. eg: `default:"def_value"` - 支持从 ENV 初始化设置字段值 `default:"${APP_ENV | dev}"` - 支持通过 `.` 分隔符来按路径获取子级值,也支持自定义分隔符。 e.g `map.key` `arr.2` -- 支持解析ENV变量名称。 like `shell: ${SHELL}` -> `shell: /bin/zsh` +- 支持在配置数据更改时触发事件 + - 可用事件: `set.value`, `set.data`, `load.data`, `clean.data`, `reload.data` - 简洁的使用API `Get` `Int` `Uint` `Int64` `String` `Bool` `Ints` `IntMap` `Strings` `StringMap` ... - 完善的单元测试(code coverage > 95%) @@ -88,7 +94,7 @@ import ( // go run ./examples/yaml.go func main() { - // 设置选项支持 ENV 解析 + // 设置选项支持ENV变量解析:当获取的值为string类型时,会尝试解析其中的ENV变量 config.WithOptions(config.ParseEnv) // 添加驱动程序以支持yaml内容解析(除了JSON是默认支持,其他的则是按需使用) @@ -334,7 +340,7 @@ ioutil.WriteFile("my-config.yaml", buf.Bytes(), 0755) ```go // Options config options type Options struct { - // parse env value. like: "${EnvName}" "${EnvName|default}" + // parse env in string value. like: "${EnvName}" "${EnvName|default}" ParseEnv bool // ParseTime parses a duration string to time.Duration // eg: 10s, 2m @@ -345,8 +351,6 @@ type Options struct { EnableCache bool // parse key, allow find value by key path. default is True eg: 'key.sub' will find `map[key]sub` ParseKey bool - // tag name for binding data to struct - TagName string // the delimiter char for split key, when `FindByPath=true`. default is '.' Delimiter byte // default write format. default is JSON @@ -362,6 +366,15 @@ type Options struct { } ``` +Examples for set options: + +```go +config.WithOptions(config.WithTagName("mytag")) +config.WithOptions(func(opt *Options) { + opt.SetTagNames("config") +}) +``` + ### 选项: 解析默认值 NEW: 支持通过结构标签 `default` 解析并设置默认值 diff --git a/vendor/github.com/gookit/config/v2/config.go b/vendor/github.com/gookit/config/v2/config.go index 4c708c93a3..d52515bc4b 100644 --- a/vendor/github.com/gookit/config/v2/config.go +++ b/vendor/github.com/gookit/config/v2/config.go @@ -111,23 +111,24 @@ type Config struct { sMapCache map[string]strMap } -// New config instance, default add JSON driver +// New config instance with custom options, default with JSON driver func New(name string, opts ...OptionFn) *Config { - return NewEmpty(name).WithDriver(JSONDriver).WithOptions(opts...) + return NewEmpty(name, opts...).WithDriver(JSONDriver) } -// NewEmpty config instance -func NewEmpty(name string) *Config { - return &Config{ +// NewEmpty create config instance with custom options +func NewEmpty(name string, opts ...OptionFn) *Config { + c := &Config{ name: name, opts: newDefaultOption(), data: make(map[string]any), - // don't add any drivers encoders: map[string]Encoder{}, decoders: map[string]Decoder{}, aliasMap: make(map[string]string), } + + return c.WithOptions(opts...) } // NewWith create config instance, and you can call some init func diff --git a/vendor/github.com/gookit/config/v2/export.go b/vendor/github.com/gookit/config/v2/export.go index d6e7c573cb..7f20b61794 100644 --- a/vendor/github.com/gookit/config/v2/export.go +++ b/vendor/github.com/gookit/config/v2/export.go @@ -121,7 +121,7 @@ func (c *Config) Structure(key string, dst any) (err error) { return err } -// ToJSON string +// ToJSON string, will ignore error func (c *Config) ToJSON() string { buf := &bytes.Buffer{} @@ -129,7 +129,6 @@ func (c *Config) ToJSON() string { if err != nil { return "" } - return buf.String() } @@ -168,7 +167,6 @@ func (c *Config) DumpTo(out io.Writer, format string) (n int64, err error) { // write content to out num, _ := fmt.Fprintln(out, string(encoded)) - return int64(num), nil } diff --git a/vendor/github.com/gookit/config/v2/load.go b/vendor/github.com/gookit/config/v2/load.go index 38becdf8c2..e90f634e8d 100644 --- a/vendor/github.com/gookit/config/v2/load.go +++ b/vendor/github.com/gookit/config/v2/load.go @@ -12,9 +12,9 @@ import ( "strings" "time" + "dario.cat/mergo" "github.com/gookit/goutil/errorx" "github.com/gookit/goutil/fsutil" - "github.com/imdario/mergo" ) // LoadFiles load one or multi files, will fire OnLoadData event @@ -103,10 +103,8 @@ func (c *Config) LoadOSEnv(keys []string, keyToLower bool) { if keyToLower { key = strings.ToLower(key) } - _ = c.Set(key, val) } - c.fireHook(OnLoadData) } @@ -195,7 +193,7 @@ func LoadData(dataSource ...any) error { return dc.LoadData(dataSource...) } // LoadData load data from map OR struct // -// The dataSources can be: +// The dataSources type allow: // - map[string]any // - map[string]string func (c *Config) LoadData(dataSources ...any) (err error) { @@ -203,19 +201,24 @@ func (c *Config) LoadData(dataSources ...any) (err error) { c.opts.Delimiter = defaultDelimiter } + var loaded bool for _, ds := range dataSources { if smp, ok := ds.(map[string]string); ok { + loaded = true c.LoadSMap(smp) continue } - err = mergo.Merge(&c.data, ds, mergo.WithOverride) + err = mergo.Merge(&c.data, ds, c.opts.MergeOptions...) if err != nil { return errorx.WithStack(err) } + loaded = true } - c.fireHook(OnLoadData) + if loaded { + c.fireHook(OnLoadData) + } return } @@ -237,8 +240,8 @@ func LoadSources(format string, src []byte, more ...[]byte) error { // Usage: // // config.LoadSources(config.Yaml, []byte(` -// name: blog -// arr: +// name: blog +// arr: // key: val // // `)) @@ -308,6 +311,24 @@ func (c *Config) LoadExistsByFormat(format string, configFiles ...string) (err e return } +// LoadOptions for load config from dir. +type LoadOptions struct { + // DataKey use for load config from dir. + // see https://github.com/gookit/config/issues/173 + DataKey string +} + +// LoadOptFn type func +type LoadOptFn func(lo *LoadOptions) + +func newLoadOptions(loFns []LoadOptFn) *LoadOptions { + lo := &LoadOptions{} + for _, fn := range loFns { + fn(lo) + } + return lo +} + // LoadFromDir Load custom format files from the given directory, the file name will be used as the key. // // Example: @@ -317,24 +338,30 @@ func (c *Config) LoadExistsByFormat(format string, configFiles ...string) (err e // // // after load // Config.data = map[string]any{"task": file data} -func LoadFromDir(dirPath, format string) error { - return dc.LoadFromDir(dirPath, format) +func LoadFromDir(dirPath, format string, loFns ...LoadOptFn) error { + return dc.LoadFromDir(dirPath, format, loFns...) } // LoadFromDir Load custom format files from the given directory, the file name will be used as the key. // +// NOTE: will not be reloaded on call ReloadFiles(), if data loaded by the method. +// // Example: // -// // file: /somedir/task.json +// // file: /somedir/task.json , will use filename 'task' as key // Config.LoadFromDir("/somedir", "json") // -// // after load -// Config.data = map[string]any{"task": file data} -func (c *Config) LoadFromDir(dirPath, format string) (err error) { +// // after load, the data will be: +// Config.data = map[string]any{"task": {file data}} +func (c *Config) LoadFromDir(dirPath, format string, loFns ...LoadOptFn) (err error) { extName := "." + format extLen := len(extName) - return fsutil.FindInDir(dirPath, func(fPath string, ent fs.DirEntry) error { + lo := newLoadOptions(loFns) + dirData := make(map[string]any) + dataList := make([]map[string]any, 0, 8) + + err = fsutil.FindInDir(dirPath, func(fPath string, ent fs.DirEntry) error { baseName := ent.Name() if strings.HasSuffix(baseName, extName) { data, err := c.parseSourceToMap(format, fsutil.MustReadFile(fPath)) @@ -342,18 +369,31 @@ func (c *Config) LoadFromDir(dirPath, format string) (err error) { return err } + // filename without ext. onlyName := baseName[:len(baseName)-extLen] - err = c.loadDataMap(map[string]any{onlyName: data}) + if lo.DataKey != "" { + dataList = append(dataList, data) + } else { + dirData[onlyName] = data + } - // use file name as key, it cannot be reloaded. SO, cannot append to loadedFiles - // if err == nil { - // c.loadedFiles = append(c.loadedFiles, fPath) - // } - - return err + // TODO use file name as key, it cannot be reloaded. So, cannot append to loadedFiles + // c.loadedFiles = append(c.loadedFiles, fPath) } return nil }) + + if err != nil { + return err + } + if lo.DataKey != "" { + dirData[lo.DataKey] = dataList + } + + if len(dirData) == 0 { + return nil + } + return c.loadDataMap(dirData) } // ReloadFiles reload config data use loaded files @@ -440,7 +480,7 @@ func (c *Config) loadDataMap(data map[string]any) (err error) { c.data = data } else { // again ... will merge data - err = mergo.Merge(&c.data, data, mergo.WithOverride, mergo.WithTypeCheck) + err = mergo.Merge(&c.data, data, c.opts.MergeOptions...) } if !c.reloading && err == nil { diff --git a/vendor/github.com/gookit/config/v2/options.go b/vendor/github.com/gookit/config/v2/options.go index 595468f854..f58e83668c 100644 --- a/vendor/github.com/gookit/config/v2/options.go +++ b/vendor/github.com/gookit/config/v2/options.go @@ -3,6 +3,8 @@ package config import ( "strings" + "dario.cat/mergo" + "github.com/gookit/goutil" "github.com/mitchellh/mapstructure" ) @@ -20,20 +22,22 @@ type HookFunc func(event string, c *Config) // Options config options type Options struct { - // ParseEnv parse env value. like: "${EnvName}" "${EnvName|default}" + // ParseEnv parse env in string value and default value. like: "${EnvName}" "${EnvName|default}" ParseEnv bool // ParseTime parses a duration string to time.Duration // eg: 10s, 2m ParseTime bool // Readonly config is readonly Readonly bool + // ParseDefault tag on binding data to struct. tag: default + ParseDefault bool // EnableCache enable config data cache EnableCache bool // ParseKey parse key path, allow find value by key path. eg: 'key.sub' will find `map[key]sub` ParseKey bool // TagName tag name for binding data to struct // - // Tips: please set tag name by DecoderConfig + // Deprecated: please set tag name by DecoderConfig, or use SetTagName() TagName string // Delimiter the delimiter char for split key path, if `FindByPath=true`. default is '.' Delimiter byte @@ -45,8 +49,8 @@ type Options struct { DecoderConfig *mapstructure.DecoderConfig // HookFunc on data changed. you can do something... HookFunc HookFunc - // ParseDefault tag on binding data to struct. tag: default - ParseDefault bool + // MergeOptions settings for merge two data + MergeOptions []func(*mergo.Config) // WatchChange bool } @@ -63,6 +67,10 @@ func newDefaultOption() *Options { ReadFormat: JSON, // struct decoder config DecoderConfig: newDefaultDecoderConfig(""), + MergeOptions: []func(*mergo.Config){ + mergo.WithOverride, + mergo.WithTypeCheck, + }, } } @@ -79,6 +87,12 @@ func newDefaultDecoderConfig(tagName string) *mapstructure.DecoderConfig { } } +// SetTagName for mapping data to struct +func (o *Options) SetTagName(tagName string) { + o.TagName = tagName + o.DecoderConfig.TagName = tagName +} + func (o *Options) shouldAddHookFunc() bool { return o.ParseTime || o.ParseEnv } @@ -113,8 +127,7 @@ func (o *Options) makeDecoderConfig() *mapstructure.DecoderConfig { // WithTagName set tag name for export to struct func WithTagName(tagName string) func(*Options) { return func(opts *Options) { - opts.TagName = tagName - opts.DecoderConfig.TagName = tagName + opts.SetTagName(tagName) } } @@ -137,15 +150,12 @@ func Delimiter(sep byte) func(*Options) { } } -// SaveFileOnSet set hook func +// SaveFileOnSet set hook func, will panic on save error func SaveFileOnSet(fileName string, format string) func(options *Options) { return func(opts *Options) { opts.HookFunc = func(event string, c *Config) { if strings.HasPrefix(event, "set.") { - err := c.DumpToFile(fileName, format) - if err != nil { - panic(err) - } + goutil.PanicErr(c.DumpToFile(fileName, format)) } } } diff --git a/vendor/github.com/gookit/goutil/README.md b/vendor/github.com/gookit/goutil/README.md index b9747fa47a..22cd6255ef 100644 --- a/vendor/github.com/gookit/goutil/README.md +++ b/vendor/github.com/gookit/goutil/README.md @@ -664,7 +664,6 @@ func SizeToString(size uint64) string func StringToByte(sizeStr string) uint64 func ParseByte(sizeStr string) uint64 func PrettyJSON(v any) (string, error) -func StringsToInts(ss []string) (ints []int, err error) func ArgsWithSpaces(vs []any) (message string) // source at fmtutil/time.go func HowLongAgo(sec int64) string @@ -909,6 +908,8 @@ func SimpleMerge(src, dst map[string]any) map[string]any func DeepMerge(src, dst map[string]any, deep int) map[string]any func MergeSMap(src, dst map[string]string, ignoreCase bool) map[string]string func MergeStringMap(src, dst map[string]string, ignoreCase bool) map[string]string +func MergeMultiSMap(mps ...map[string]string) map[string]string +func FilterSMap(sm map[string]string) map[string]string func MakeByPath(path string, val any) (mp map[string]any) func MakeByKeys(keys []string, val any) (mp map[string]any) // source at maputil/setval.go @@ -942,36 +943,49 @@ func MaxI64(x, y int64) int64 func SwapMaxI64(x, y int64) (int64, int64) func MaxFloat(x, y float64) float64 // source at mathutil/convert.go +func NewConvOption[T any](optFns ...ConvOptionFn[T]) *ConvOption[T] +func WithNilAsFail[T any](opt *ConvOption[T]) +func WithHandlePtr[T any](opt *ConvOption[T]) +func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T] func Int(in any) (int, error) func SafeInt(in any) int func QuietInt(in any) int -func MustInt(in any) int func IntOrPanic(in any) int +func MustInt(in any) int func IntOrDefault(in any, defVal int) int func IntOr(in any, defVal int) int -func IntOrErr(in any) (iVal int, err error) -func ToInt(in any) (iVal int, err error) -func ToIntWithFunc(in any, usrFn ToIntFunc) (iVal int, err error) +func IntOrErr(in any) (int, error) +func ToInt(in any) (int, error) +func ToIntWith(in any, optFns ...ConvOptionFn[int]) (iVal int, err error) func StrInt(s string) int func StrIntOr(s string, defVal int) int -func Uint(in any) (uint64, error) -func SafeUint(in any) uint64 -func QuietUint(in any) uint64 -func MustUint(in any) uint64 -func UintOrDefault(in any, defVal uint64) uint64 -func UintOr(in any, defVal uint64) uint64 -func UintOrErr(in any) (uint64, error) -func ToUint(in any) (u64 uint64, err error) -func ToUintWithFunc(in any, usrFn ToUintFunc) (u64 uint64, err error) func Int64(in any) (int64, error) func SafeInt64(in any) int64 func QuietInt64(in any) int64 func MustInt64(in any) int64 func Int64OrDefault(in any, defVal int64) int64 func Int64Or(in any, defVal int64) int64 +func ToInt64(in any) (int64, error) func Int64OrErr(in any) (int64, error) -func ToInt64(in any) (i64 int64, err error) -func ToInt64WithFunc(in any, usrFn ToInt64Func) (i64 int64, err error) +func ToInt64With(in any, optFns ...ConvOptionFn[int64]) (i64 int64, err error) +func Uint(in any) (uint, error) +func SafeUint(in any) uint +func QuietUint(in any) uint +func MustUint(in any) uint +func UintOrDefault(in any, defVal uint) uint +func UintOr(in any, defVal uint) uint +func UintOrErr(in any) (uint, error) +func ToUint(in any) (u64 uint, err error) +func ToUintWith(in any, optFns ...ConvOptionFn[uint]) (uVal uint, err error) +func Uint64(in any) (uint64, error) +func QuietUint64(in any) uint64 +func SafeUint64(in any) uint64 +func MustUint64(in any) uint64 +func Uint64OrDefault(in any, defVal uint64) uint64 +func Uint64Or(in any, defVal uint64) uint64 +func Uint64OrErr(in any) (uint64, error) +func ToUint64(in any) (uint64, error) +func ToUint64With(in any, optFns ...ConvOptionFn[uint64]) (u64 uint64, err error) func QuietFloat(in any) float64 func SafeFloat(in any) float64 func FloatOrPanic(in any) float64 @@ -980,8 +994,8 @@ func FloatOrDefault(in any, defVal float64) float64 func FloatOr(in any, defVal float64) float64 func Float(in any) (float64, error) func FloatOrErr(in any) (float64, error) -func ToFloat(in any) (f64 float64, err error) -func ToFloatWithFunc(in any, usrFn ToFloatFunc) (f64 float64, err error) +func ToFloat(in any) (float64, error) +func ToFloatWith(in any, optFns ...ConvOptionFn[float64]) (f64 float64, err error) func MustString(val any) string func StringOrPanic(val any) string func StringOrDefault(val any, defVal string) string @@ -991,10 +1005,8 @@ func StringOrErr(val any) (string, error) func QuietString(val any) string func String(val any) string func SafeString(val any) string -func TryToString(val any, defaultAsErr bool) (str string, err error) -func ToStringWithFunc(val any, usrFn comdef.ToStringFunc) (str string, err error) -func Percent(val, total int) float64 -func ElapsedTime(startTime time.Time) string +func TryToString(val any, defaultAsErr bool) (string, error) +func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error) // source at mathutil/format.go func DataSize(size uint64) string func HowLongAgo(sec int64) string @@ -1005,11 +1017,19 @@ func LessOr[T comdef.XintOrFloat](val, max, devVal T) T func LteOr[T comdef.XintOrFloat](val, max, devVal T) T func GreaterOr[T comdef.XintOrFloat](val, min, defVal T) T func GteOr[T comdef.XintOrFloat](val, min, defVal T) T +func Mul[T1, T2 comdef.XintOrFloat](a T1, b T2) float64 +func MulF2i(a, b float64) int +func Div[T1, T2 comdef.XintOrFloat](a T1, b T2) float64 +func DivInt[T comdef.Integer](a, b T) int +func DivF2i(a, b float64) int +func Percent(val, total int) float64 // source at mathutil/random.go func RandomInt(min, max int) int func RandInt(min, max int) int func RandIntWithSeed(min, max int, seed int64) int func RandomIntWithSeed(min, max int, seed int64) int +// source at mathutil/value.go +func New[T comdef.IntOrFloat](v T) *Num[T] ``` ### Reflects @@ -1223,7 +1243,7 @@ func MustString(val any) string func StringOrDefault(val any, defVal string) string func StringOr(val any, defVal string) string func AnyToString(val any, defaultAsErr bool) (s string, err error) -func ToStringWithFunc(val any, fbFn comdef.ToStringFunc) (str string, err error) +func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error) func ToBool(s string) (bool, error) func QuietBool(s string) bool func SafeBool(s string) bool @@ -1238,8 +1258,8 @@ func QuietInt(s string) int func MustInt(s string) int func IntOrPanic(s string) int func Int64(s string) int64 -func SafeInt64(s string) int64 func QuietInt64(s string) int64 +func SafeInt64(s string) int64 func ToInt64(s string) (int64, error) func Int64OrDefault(s string, defVal int64) int64 func Int64Or(s string, defVal int64) int64 @@ -1401,9 +1421,6 @@ func OrHandle(s string, fn comdef.StringHandleFunc) string func Valid(ss ...string) string func Replaces(str string, pairs map[string]string) string func NewReplacer(pairs map[string]string) *strings.Replacer -func PrettyJSON(v any) (string, error) -func RenderTemplate(input string, data any, fns template.FuncMap, isFile ...bool) string -func RenderText(input string, data any, fns template.FuncMap, isFile ...bool) string func WrapTag(s, tag string) string func SubstrCount(s, substr string, params ...uint64) (int, error) ``` diff --git a/vendor/github.com/gookit/goutil/README.zh-CN.md b/vendor/github.com/gookit/goutil/README.zh-CN.md index 318d4976d6..aca933bed0 100644 --- a/vendor/github.com/gookit/goutil/README.zh-CN.md +++ b/vendor/github.com/gookit/goutil/README.zh-CN.md @@ -665,7 +665,6 @@ func SizeToString(size uint64) string func StringToByte(sizeStr string) uint64 func ParseByte(sizeStr string) uint64 func PrettyJSON(v any) (string, error) -func StringsToInts(ss []string) (ints []int, err error) func ArgsWithSpaces(vs []any) (message string) // source at fmtutil/time.go func HowLongAgo(sec int64) string @@ -910,6 +909,8 @@ func SimpleMerge(src, dst map[string]any) map[string]any func DeepMerge(src, dst map[string]any, deep int) map[string]any func MergeSMap(src, dst map[string]string, ignoreCase bool) map[string]string func MergeStringMap(src, dst map[string]string, ignoreCase bool) map[string]string +func MergeMultiSMap(mps ...map[string]string) map[string]string +func FilterSMap(sm map[string]string) map[string]string func MakeByPath(path string, val any) (mp map[string]any) func MakeByKeys(keys []string, val any) (mp map[string]any) // source at maputil/setval.go @@ -943,36 +944,49 @@ func MaxI64(x, y int64) int64 func SwapMaxI64(x, y int64) (int64, int64) func MaxFloat(x, y float64) float64 // source at mathutil/convert.go +func NewConvOption[T any](optFns ...ConvOptionFn[T]) *ConvOption[T] +func WithNilAsFail[T any](opt *ConvOption[T]) +func WithHandlePtr[T any](opt *ConvOption[T]) +func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T] func Int(in any) (int, error) func SafeInt(in any) int func QuietInt(in any) int -func MustInt(in any) int func IntOrPanic(in any) int +func MustInt(in any) int func IntOrDefault(in any, defVal int) int func IntOr(in any, defVal int) int -func IntOrErr(in any) (iVal int, err error) -func ToInt(in any) (iVal int, err error) -func ToIntWithFunc(in any, usrFn ToIntFunc) (iVal int, err error) +func IntOrErr(in any) (int, error) +func ToInt(in any) (int, error) +func ToIntWith(in any, optFns ...ConvOptionFn[int]) (iVal int, err error) func StrInt(s string) int func StrIntOr(s string, defVal int) int -func Uint(in any) (uint64, error) -func SafeUint(in any) uint64 -func QuietUint(in any) uint64 -func MustUint(in any) uint64 -func UintOrDefault(in any, defVal uint64) uint64 -func UintOr(in any, defVal uint64) uint64 -func UintOrErr(in any) (uint64, error) -func ToUint(in any) (u64 uint64, err error) -func ToUintWithFunc(in any, usrFn ToUintFunc) (u64 uint64, err error) func Int64(in any) (int64, error) func SafeInt64(in any) int64 func QuietInt64(in any) int64 func MustInt64(in any) int64 func Int64OrDefault(in any, defVal int64) int64 func Int64Or(in any, defVal int64) int64 +func ToInt64(in any) (int64, error) func Int64OrErr(in any) (int64, error) -func ToInt64(in any) (i64 int64, err error) -func ToInt64WithFunc(in any, usrFn ToInt64Func) (i64 int64, err error) +func ToInt64With(in any, optFns ...ConvOptionFn[int64]) (i64 int64, err error) +func Uint(in any) (uint, error) +func SafeUint(in any) uint +func QuietUint(in any) uint +func MustUint(in any) uint +func UintOrDefault(in any, defVal uint) uint +func UintOr(in any, defVal uint) uint +func UintOrErr(in any) (uint, error) +func ToUint(in any) (u64 uint, err error) +func ToUintWith(in any, optFns ...ConvOptionFn[uint]) (uVal uint, err error) +func Uint64(in any) (uint64, error) +func QuietUint64(in any) uint64 +func SafeUint64(in any) uint64 +func MustUint64(in any) uint64 +func Uint64OrDefault(in any, defVal uint64) uint64 +func Uint64Or(in any, defVal uint64) uint64 +func Uint64OrErr(in any) (uint64, error) +func ToUint64(in any) (uint64, error) +func ToUint64With(in any, optFns ...ConvOptionFn[uint64]) (u64 uint64, err error) func QuietFloat(in any) float64 func SafeFloat(in any) float64 func FloatOrPanic(in any) float64 @@ -981,8 +995,8 @@ func FloatOrDefault(in any, defVal float64) float64 func FloatOr(in any, defVal float64) float64 func Float(in any) (float64, error) func FloatOrErr(in any) (float64, error) -func ToFloat(in any) (f64 float64, err error) -func ToFloatWithFunc(in any, usrFn ToFloatFunc) (f64 float64, err error) +func ToFloat(in any) (float64, error) +func ToFloatWith(in any, optFns ...ConvOptionFn[float64]) (f64 float64, err error) func MustString(val any) string func StringOrPanic(val any) string func StringOrDefault(val any, defVal string) string @@ -992,10 +1006,8 @@ func StringOrErr(val any) (string, error) func QuietString(val any) string func String(val any) string func SafeString(val any) string -func TryToString(val any, defaultAsErr bool) (str string, err error) -func ToStringWithFunc(val any, usrFn comdef.ToStringFunc) (str string, err error) -func Percent(val, total int) float64 -func ElapsedTime(startTime time.Time) string +func TryToString(val any, defaultAsErr bool) (string, error) +func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error) // source at mathutil/format.go func DataSize(size uint64) string func HowLongAgo(sec int64) string @@ -1006,11 +1018,19 @@ func LessOr[T comdef.XintOrFloat](val, max, devVal T) T func LteOr[T comdef.XintOrFloat](val, max, devVal T) T func GreaterOr[T comdef.XintOrFloat](val, min, defVal T) T func GteOr[T comdef.XintOrFloat](val, min, defVal T) T +func Mul[T1, T2 comdef.XintOrFloat](a T1, b T2) float64 +func MulF2i(a, b float64) int +func Div[T1, T2 comdef.XintOrFloat](a T1, b T2) float64 +func DivInt[T comdef.Integer](a, b T) int +func DivF2i(a, b float64) int +func Percent(val, total int) float64 // source at mathutil/random.go func RandomInt(min, max int) int func RandInt(min, max int) int func RandIntWithSeed(min, max int, seed int64) int func RandomIntWithSeed(min, max int, seed int64) int +// source at mathutil/value.go +func New[T comdef.IntOrFloat](v T) *Num[T] ``` ### Reflects @@ -1224,7 +1244,7 @@ func MustString(val any) string func StringOrDefault(val any, defVal string) string func StringOr(val any, defVal string) string func AnyToString(val any, defaultAsErr bool) (s string, err error) -func ToStringWithFunc(val any, fbFn comdef.ToStringFunc) (str string, err error) +func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error) func ToBool(s string) (bool, error) func QuietBool(s string) bool func SafeBool(s string) bool @@ -1239,8 +1259,8 @@ func QuietInt(s string) int func MustInt(s string) int func IntOrPanic(s string) int func Int64(s string) int64 -func SafeInt64(s string) int64 func QuietInt64(s string) int64 +func SafeInt64(s string) int64 func ToInt64(s string) (int64, error) func Int64OrDefault(s string, defVal int64) int64 func Int64Or(s string, defVal int64) int64 @@ -1402,9 +1422,6 @@ func OrHandle(s string, fn comdef.StringHandleFunc) string func Valid(ss ...string) string func Replaces(str string, pairs map[string]string) string func NewReplacer(pairs map[string]string) *strings.Replacer -func PrettyJSON(v any) (string, error) -func RenderTemplate(input string, data any, fns template.FuncMap, isFile ...bool) string -func RenderText(input string, data any, fns template.FuncMap, isFile ...bool) string func WrapTag(s, tag string) string func SubstrCount(s, substr string, params ...uint64) (int, error) ``` diff --git a/vendor/github.com/gookit/goutil/comdef/comdef.go b/vendor/github.com/gookit/goutil/comdef/comdef.go index 54a16687a9..d1e0ef238d 100644 --- a/vendor/github.com/gookit/goutil/comdef/comdef.go +++ b/vendor/github.com/gookit/goutil/comdef/comdef.go @@ -9,6 +9,9 @@ type ( UnmarshalFunc func(bts []byte, ptr any) error ) +// ToTypeFunc convert value to defined type +type ToTypeFunc[T any] func(any) (T, error) + // IntCheckFunc check func type IntCheckFunc func(val int) error diff --git a/vendor/github.com/gookit/goutil/comdef/errors.go b/vendor/github.com/gookit/goutil/comdef/errors.go index c210de321c..c2f68aa943 100644 --- a/vendor/github.com/gookit/goutil/comdef/errors.go +++ b/vendor/github.com/gookit/goutil/comdef/errors.go @@ -1,6 +1,38 @@ package comdef -import "errors" +import ( + "errors" + "strings" +) // ErrConvType error var ErrConvType = errors.New("convert value type error") + +// Errors multi error list +type Errors []error + +// Error string +func (es Errors) Error() string { + var sb strings.Builder + for _, err := range es { + sb.WriteString(err.Error()) + sb.WriteByte('\n') + } + return sb.String() +} + +// ErrOrNil error +func (es Errors) ErrOrNil() error { + if len(es) == 0 { + return nil + } + return es +} + +// First error +func (es Errors) First() error { + if len(es) > 0 { + return es[0] + } + return nil +} diff --git a/vendor/github.com/gookit/goutil/comdef/interface.go b/vendor/github.com/gookit/goutil/comdef/interface.go index 7718f4263f..3f3fb81459 100644 --- a/vendor/github.com/gookit/goutil/comdef/interface.go +++ b/vendor/github.com/gookit/goutil/comdef/interface.go @@ -24,6 +24,11 @@ type Int64able interface { Int64() (int64, error) } +// Float64able interface +type Float64able interface { + Float64() (float64, error) +} + // // // Matcher type diff --git a/vendor/github.com/gookit/goutil/conv.go b/vendor/github.com/gookit/goutil/conv.go index 6e97c1a48b..b0a0c069c8 100644 --- a/vendor/github.com/gookit/goutil/conv.go +++ b/vendor/github.com/gookit/goutil/conv.go @@ -57,17 +57,28 @@ func ToInt64(v any) (int64, error) { return mathutil.ToInt64(v) } -// Uint convert value to uint64 -func Uint(v any) uint64 { +// Uint convert value to uint +func Uint(v any) uint { iv, _ := mathutil.ToUint(v) return iv } -// ToUint try to convert value to uint64 -func ToUint(v any) (uint64, error) { +// ToUint try to convert value to uint +func ToUint(v any) (uint, error) { return mathutil.ToUint(v) } +// Uint64 convert value to uint64 +func Uint64(v any) uint64 { + iv, _ := mathutil.ToUint64(v) + return iv +} + +// ToUint64 try to convert value to uint64 +func ToUint64(v any) (uint64, error) { + return mathutil.ToUint64(v) +} + // BoolString convert bool to string func BoolString(bl bool) string { return strconv.FormatBool(bl) @@ -166,12 +177,12 @@ func ToKind(val any, kind reflect.Kind, fbFunc func(val any) (any, error)) (newV newVal = dstV } case reflect.Uint: - var dstV uint64 + var dstV uint if dstV, err = mathutil.ToUint(val); err == nil { - newVal = uint(dstV) + newVal = dstV } case reflect.Uint8: - var dstV uint64 + var dstV uint if dstV, err = mathutil.ToUint(val); err == nil { if dstV > math.MaxUint8 { return nil, fmt.Errorf("value overflow uint8. val: %v", val) @@ -179,7 +190,7 @@ func ToKind(val any, kind reflect.Kind, fbFunc func(val any) (any, error)) (newV newVal = uint8(dstV) } case reflect.Uint16: - var dstV uint64 + var dstV uint if dstV, err = mathutil.ToUint(val); err == nil { if dstV > math.MaxUint16 { return nil, fmt.Errorf("value overflow uint16. val: %v", val) @@ -187,7 +198,7 @@ func ToKind(val any, kind reflect.Kind, fbFunc func(val any) (any, error)) (newV newVal = uint16(dstV) } case reflect.Uint32: - var dstV uint64 + var dstV uint if dstV, err = mathutil.ToUint(val); err == nil { if dstV > math.MaxUint32 { return nil, fmt.Errorf("value overflow uint32. val: %v", val) @@ -196,7 +207,7 @@ func ToKind(val any, kind reflect.Kind, fbFunc func(val any) (any, error)) (newV } case reflect.Uint64: var dstV uint64 - if dstV, err = mathutil.ToUint(val); err == nil { + if dstV, err = mathutil.ToUint64(val); err == nil { newVal = dstV } case reflect.Float32: diff --git a/vendor/github.com/gookit/goutil/encodes/encodes.go b/vendor/github.com/gookit/goutil/encodes/encodes.go index 306325ea20..68da3bcfce 100644 --- a/vendor/github.com/gookit/goutil/encodes/encodes.go +++ b/vendor/github.com/gookit/goutil/encodes/encodes.go @@ -1,3 +1,4 @@ +// Package encodes provide some util for encode/decode data package encodes import ( diff --git a/vendor/github.com/gookit/goutil/fsutil/opwrite.go b/vendor/github.com/gookit/goutil/fsutil/opwrite.go index 64e3a1bacd..09fd2fcfd7 100644 --- a/vendor/github.com/gookit/goutil/fsutil/opwrite.go +++ b/vendor/github.com/gookit/goutil/fsutil/opwrite.go @@ -57,7 +57,8 @@ func TempDir(dir, pattern string) (string, error) { // MustSave create file and write contents to file, panic on error. // -// data type allow: string, []byte, io.Reader +// - data type allow: string, []byte, io.Reader +// // default option see NewOpenOption() func MustSave(filePath string, data any, optFns ...OpenOptionFunc) { basefn.MustOK(SaveFile(filePath, data, optFns...)) @@ -65,6 +66,8 @@ func MustSave(filePath string, data any, optFns ...OpenOptionFunc) { // SaveFile create file and write contents to file. will auto create dir. // +// - data type allow: string, []byte, io.Reader +// // default option see NewOpenOption() func SaveFile(filePath string, data any, optFns ...OpenOptionFunc) error { opt := NewOpenOption(optFns...) diff --git a/vendor/github.com/gookit/goutil/func.go b/vendor/github.com/gookit/goutil/func.go index 285e83fac6..a68a418811 100644 --- a/vendor/github.com/gookit/goutil/func.go +++ b/vendor/github.com/gookit/goutil/func.go @@ -46,7 +46,7 @@ func SafeRun(fn func()) (err error) { return nil } -// SafeRun sync run a func with error. +// SafeRunWithError sync run a func with error. // If the func panics, the panic value is returned as an error. func SafeRunWithError(fn func() error) (err error) { defer func() { diff --git a/vendor/github.com/gookit/goutil/internal/checkfn/check.go b/vendor/github.com/gookit/goutil/internal/checkfn/check.go index b6c5629867..3562047848 100644 --- a/vendor/github.com/gookit/goutil/internal/checkfn/check.go +++ b/vendor/github.com/gookit/goutil/internal/checkfn/check.go @@ -1,11 +1,10 @@ package checkfn import ( + "bytes" "fmt" "reflect" "strings" - - "github.com/gookit/goutil/reflects" ) // IsNil value check @@ -13,15 +12,46 @@ func IsNil(v any) bool { if v == nil { return true } - return reflects.IsNil(reflect.ValueOf(v)) + + rv := reflect.ValueOf(v) + switch rv.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return rv.IsNil() + default: + return false + } } -// IsEmpty value check -func IsEmpty(v any) bool { - if v == nil { +// IsSimpleKind kind in: string, bool, intX, uintX, floatX +func IsSimpleKind(k reflect.Kind) bool { + if reflect.String == k { return true } - return reflects.IsEmpty(reflect.ValueOf(v)) + return k > reflect.Invalid && k <= reflect.Float64 +} + +// IsEqual determines if two objects are considered equal. +// +// TIP: cannot compare function type +func IsEqual(src, dst any) bool { + if src == nil || dst == nil { + return src == dst + } + + bs1, ok := src.([]byte) + if !ok { + return reflect.DeepEqual(src, dst) + } + + bs2, ok := dst.([]byte) + if !ok { + return false + } + + if bs1 == nil || bs2 == nil { + return bs1 == nil && bs2 == nil + } + return bytes.Equal(bs1, bs2) } // Contains try loop over the data check if the data includes the element. @@ -57,7 +87,7 @@ func Contains(data, elem any) (valid, found bool) { if dataKind == reflect.Map { mapKeys := dataRv.MapKeys() for i := 0; i < len(mapKeys); i++ { - if reflects.IsEqual(mapKeys[i].Interface(), elem) { + if IsEqual(mapKeys[i].Interface(), elem) { return true, true } } @@ -70,7 +100,7 @@ func Contains(data, elem any) (valid, found bool) { } for i := 0; i < dataRv.Len(); i++ { - if reflects.IsEqual(dataRv.Index(i).Interface(), elem) { + if IsEqual(dataRv.Index(i).Interface(), elem) { return true, true } } diff --git a/vendor/github.com/gookit/goutil/internal/comfunc/comfunc.go b/vendor/github.com/gookit/goutil/internal/comfunc/comfunc.go index 8a3206131d..5b2ad153a9 100644 --- a/vendor/github.com/gookit/goutil/internal/comfunc/comfunc.go +++ b/vendor/github.com/gookit/goutil/internal/comfunc/comfunc.go @@ -16,7 +16,6 @@ func Environ() map[string]string { for _, str := range envList { nodes := strings.SplitN(str, "=", 2) - if len(nodes) < 2 { envMap[nodes[0]] = "" } else { diff --git a/vendor/github.com/gookit/goutil/internal/comfunc/convert.go b/vendor/github.com/gookit/goutil/internal/comfunc/convert.go index c3a015e82e..3d4f3b278e 100644 --- a/vendor/github.com/gookit/goutil/internal/comfunc/convert.go +++ b/vendor/github.com/gookit/goutil/internal/comfunc/convert.go @@ -2,9 +2,13 @@ package comfunc import ( "fmt" + "reflect" + "strconv" "strings" + "time" "github.com/gookit/goutil/comdef" + "github.com/gookit/goutil/internal/checkfn" ) // Bool try to convert type to bool @@ -60,3 +64,117 @@ func FormatWithArgs(fmtAndArgs []any) string { } return fmt.Sprint(fmtAndArgs...) } + +// ConvOption convert options +type ConvOption struct { + // if ture: value is nil, will return convert error; + // if false(default): value is nil, will convert to zero value + NilAsFail bool + // HandlePtr auto convert ptr type(int,float,string) value. eg: *int to int + // - if true: will use real type try convert. default is false + // - NOTE: current T type's ptr is default support. + HandlePtr bool + // set custom fallback convert func for not supported type. + UserConvFn comdef.ToStringFunc +} + +// ConvOptionFn convert option func +type ConvOptionFn func(opt *ConvOption) + +// StrBySprintFn convert any value to string by fmt.Sprint +var StrBySprintFn = func(v any) (string, error) { + return fmt.Sprint(v), nil +} + +// WithHandlePtr set ConvOption.HandlePtr option +func WithHandlePtr(opt *ConvOption) { + opt.HandlePtr = true +} + +// WithUserConvFn set ConvOption.UserConvFn option +func WithUserConvFn(fn comdef.ToStringFunc) ConvOptionFn { + return func(opt *ConvOption) { + opt.UserConvFn = fn + } +} + +// NewConvOption create a new ConvOption +func NewConvOption(optFns ...ConvOptionFn) *ConvOption { + opt := &ConvOption{} + opt.WithOption(optFns...) + return opt +} + +// WithOption set convert option +func (opt *ConvOption) WithOption(optFns ...ConvOptionFn) { + for _, fn := range optFns { + if fn != nil { + fn(opt) + } + } +} + +// ToStringWith try to convert value to string. can with some option func, more see ConvOption. +func ToStringWith(in any, optFns ...ConvOptionFn) (str string, err error) { + opt := NewConvOption(optFns...) + if !opt.NilAsFail && in == nil { + return "", nil + } + + switch value := in.(type) { + case int: + str = strconv.Itoa(value) + case int8: + str = strconv.Itoa(int(value)) + case int16: + str = strconv.Itoa(int(value)) + case int32: // same as `rune` + str = strconv.Itoa(int(value)) + case int64: + str = strconv.FormatInt(value, 10) + case uint: + str = strconv.FormatUint(uint64(value), 10) + case uint8: + str = strconv.FormatUint(uint64(value), 10) + case uint16: + str = strconv.FormatUint(uint64(value), 10) + case uint32: + str = strconv.FormatUint(uint64(value), 10) + case uint64: + str = strconv.FormatUint(value, 10) + case float32: + str = strconv.FormatFloat(float64(value), 'f', -1, 32) + case float64: + str = strconv.FormatFloat(value, 'f', -1, 64) + case bool: + str = strconv.FormatBool(value) + case string: + str = value + case *string: + str = *value + case []byte: + str = string(value) + case time.Duration: + str = strconv.FormatInt(int64(value), 10) + case fmt.Stringer: + str = value.String() + case error: + str = value.Error() + default: + if opt.HandlePtr { + if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer { + rv = rv.Elem() + if checkfn.IsSimpleKind(rv.Kind()) { + return ToStringWith(rv.Interface(), optFns...) + } + } + } + + if opt.UserConvFn != nil { + str, err = opt.UserConvFn(in) + } else { + err = comdef.ErrConvType + } + } + return +} diff --git a/vendor/github.com/gookit/goutil/internal/varexpr/varexpr.go b/vendor/github.com/gookit/goutil/internal/varexpr/varexpr.go index 3c400f9cb7..bc701008db 100644 --- a/vendor/github.com/gookit/goutil/internal/varexpr/varexpr.go +++ b/vendor/github.com/gookit/goutil/internal/varexpr/varexpr.go @@ -20,8 +20,14 @@ import ( "strings" ) -// SepChar separator char -const SepChar = "|" +const ( + // SepChar separator char split var name and default value + SepChar = "|" + VarLeft = "${" // default var left format chars + VarRight = "}" // default var right format chars + + mustPrefix = '?' // must prefix char +) // ParseOptFn option func type ParseOptFn func(o *ParseOpts) @@ -34,8 +40,15 @@ type ParseOpts struct { ParseFn func(string) (string, error) // Regexp custom expression regex. Regexp *regexp.Regexp - // Keyword check chars for expression. default is "${" - Keyword string + // var format chars for expression. + // default left="${", right="}" + VarLeft, VarRight string +} + +func (opt *ParseOpts) useDefaultRegex() { + opt.Regexp = envRegex + opt.VarLeft = VarLeft + opt.VarRight = VarRight } // must add "?" - To ensure that there is no greedy match @@ -71,15 +84,12 @@ type Parser struct { // New create a new Parser func New(optFns ...ParseOptFn) *Parser { - opts := &ParseOpts{ - Getter: os.Getenv, - Regexp: envRegex, - Keyword: "${", - } + opts := &ParseOpts{Getter: os.Getenv} + opts.useDefaultRegex() + for _, fn := range optFns { fn(opts) } - return &Parser{ParseOpts: *opts} } @@ -92,13 +102,19 @@ func New(optFns ...ParseOptFn) *Parser { // ${var_name | ?error} With error on value is empty. func (p *Parser) Parse(val string) (newVal string, err error) { if p.Regexp == nil { - p.Regexp = envRegex + p.useDefaultRegex() } - if p.Keyword != "" && !strings.Contains(val, p.Keyword) { + times := strings.Count(val, p.VarLeft) + if times == 0 { return val, nil } + // enhance: see https://github.com/gookit/goutil/issues/135 + if times == 1 && strings.HasPrefix(val, p.VarLeft) && strings.HasSuffix(val, p.VarRight) { + return p.parseOne(val) + } + // parse expression newVal = p.Regexp.ReplaceAllStringFunc(val, func(s string) string { if err != nil { @@ -116,11 +132,11 @@ func (p *Parser) parseOne(eVar string) (val string, err error) { return p.ParseFn(eVar) } - // eVar like "${NotExist|defValue}", first remove "${" and "}", then split it + // like "${NotExist | defValue}". first remove "${" and "}", then split it ss := strings.SplitN(eVar[2:len(eVar)-1], SepChar, 2) var name, def string - // with default value. ${NotExist|defValue} + // with default value. if len(ss) == 2 { name, def = strings.TrimSpace(ss[0]), strings.TrimSpace(ss[1]) } else { @@ -131,7 +147,7 @@ func (p *Parser) parseOne(eVar string) (val string, err error) { val = p.Getter(name) if val == "" && def != "" { // check def is "?error" - if def[0] == '?' { + if def[0] == mustPrefix { msg := "value is required for var: " + name if len(def) > 1 { msg = def[1:] diff --git a/vendor/github.com/gookit/goutil/maputil/data.go b/vendor/github.com/gookit/goutil/maputil/data.go index 07008e78f6..b284d88924 100644 --- a/vendor/github.com/gookit/goutil/maputil/data.go +++ b/vendor/github.com/gookit/goutil/maputil/data.go @@ -20,8 +20,8 @@ func (d Data) Has(key string) bool { return ok } -// IsEmtpy if the data map -func (d Data) IsEmtpy() bool { +// IsEmpty if the data map +func (d Data) IsEmpty() bool { return len(d) == 0 } @@ -127,13 +127,21 @@ func (d Data) Int64(key string) int64 { } // Uint value get -func (d Data) Uint(key string) uint64 { +func (d Data) Uint(key string) uint { if val, ok := d.GetByPath(key); ok { return mathutil.QuietUint(val) } return 0 } +// Uint64 value get +func (d Data) Uint64(key string) uint64 { + if val, ok := d.GetByPath(key); ok { + return mathutil.QuietUint64(val) + } + return 0 +} + // Str value get by key func (d Data) Str(key string) string { if val, ok := d.GetByPath(key); ok { @@ -223,6 +231,16 @@ func (d Data) Sub(key string) Data { return nil } +// Slice get []any value from data map +func (d Data) Slice(key string) ([]any, error) { + val, ok := d.GetByPath(key) + if !ok { + return nil, nil + } + + return arrutil.AnyToSlice(val) +} + // Keys of the data map func (d Data) Keys() []string { keys := make([]string, 0, len(d)) diff --git a/vendor/github.com/gookit/goutil/maputil/maputil.go b/vendor/github.com/gookit/goutil/maputil/maputil.go index 96247fd92f..795860164a 100644 --- a/vendor/github.com/gookit/goutil/maputil/maputil.go +++ b/vendor/github.com/gookit/goutil/maputil/maputil.go @@ -16,8 +16,7 @@ const ( KeySepChar = '.' ) -// SimpleMerge simple merge two data map by string key. -// will merge the src to dst map +// SimpleMerge simple merge two data map by string key. will merge the src to dst map func SimpleMerge(src, dst map[string]any) map[string]any { if len(src) == 0 { return dst @@ -66,6 +65,27 @@ func MergeStringMap(src, dst map[string]string, ignoreCase bool) map[string]stri return dst } +// MergeMultiSMap quick merge multi string-map data. +func MergeMultiSMap(mps ...map[string]string) map[string]string { + newMp := make(map[string]string) + for _, mp := range mps { + for k, v := range mp { + newMp[k] = v + } + } + return newMp +} + +// FilterSMap filter empty elem for the string map. +func FilterSMap(sm map[string]string) map[string]string { + for key, val := range sm { + if val == "" { + delete(sm, key) + } + } + return sm +} + // MakeByPath build new value by key names // // Example: diff --git a/vendor/github.com/gookit/goutil/maputil/smap.go b/vendor/github.com/gookit/goutil/maputil/smap.go index bcc74cc5e3..8905825b5f 100644 --- a/vendor/github.com/gookit/goutil/maputil/smap.go +++ b/vendor/github.com/gookit/goutil/maputil/smap.go @@ -105,6 +105,20 @@ func (m SMap) Strings(key string) (ss []string) { return } +// IfExist key, then call the fn with value. +func (m SMap) IfExist(key string, fn func(val string)) { + if val, ok := m[key]; ok { + fn(val) + } +} + +// IfValid value is not empty, then call the fn +func (m SMap) IfValid(key string, fn func(val string)) { + if val, ok := m[key]; ok && val != "" { + fn(val) + } +} + // Keys of the string-map func (m SMap) Keys() []string { keys := make([]string, 0, len(m)) diff --git a/vendor/github.com/gookit/goutil/mathutil/convert.go b/vendor/github.com/gookit/goutil/mathutil/convert.go index 1d405714a1..0369519f23 100644 --- a/vendor/github.com/gookit/goutil/mathutil/convert.go +++ b/vendor/github.com/gookit/goutil/mathutil/convert.go @@ -3,11 +3,14 @@ package mathutil import ( "fmt" "math" + "reflect" "strconv" "strings" "time" "github.com/gookit/goutil/comdef" + "github.com/gookit/goutil/internal/checkfn" + "github.com/gookit/goutil/internal/comfunc" ) // ToIntFunc convert value to int @@ -17,19 +20,76 @@ type ToIntFunc func(any) (int, error) type ToInt64Func func(any) (int64, error) // ToUintFunc convert value to uint -type ToUintFunc func(any) (uint64, error) +type ToUintFunc func(any) (uint, error) + +// ToUint64Func convert value to uint +type ToUint64Func func(any) (uint64, error) // ToFloatFunc convert value to float type ToFloatFunc func(any) (float64, error) +// ToTypeFunc convert value to defined type +type ToTypeFunc[T any] func(any) (T, error) + +// ConvOption convert options +type ConvOption[T any] struct { + // if ture: value is nil, will return convert error; + // if false(default): value is nil, will convert to zero value + NilAsFail bool + // HandlePtr auto convert ptr type(int,float,string) value. eg: *int to int + // - if true: will use real type try convert. default is false + // - NOTE: current T type's ptr is default support. + HandlePtr bool + // set custom fallback convert func for not supported type. + UserConvFn ToTypeFunc[T] +} + +// NewConvOption create a new ConvOption +func NewConvOption[T any](optFns ...ConvOptionFn[T]) *ConvOption[T] { + opt := &ConvOption[T]{} + opt.WithOption(optFns...) + return opt +} + +// WithOption set convert option +func (opt *ConvOption[T]) WithOption(optFns ...ConvOptionFn[T]) { + for _, fn := range optFns { + if fn != nil { + fn(opt) + } + } +} + +// ConvOptionFn convert option func +type ConvOptionFn[T any] func(opt *ConvOption[T]) + +// WithNilAsFail set ConvOption.NilAsFail option +// +// Example: +// +// ToIntWithFunc(val, mathutil.WithNilAsFail[int]) +func WithNilAsFail[T any](opt *ConvOption[T]) { + opt.NilAsFail = true +} + +// WithHandlePtr set ConvOption.HandlePtr option +func WithHandlePtr[T any](opt *ConvOption[T]) { + opt.HandlePtr = true +} + +// WithUserConvFn set ConvOption.UserConvFn option +func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T] { + return func(opt *ConvOption[T]) { + opt.UserConvFn = fn + } +} + /************************************************************* * convert value to int *************************************************************/ // Int convert value to int -func Int(in any) (int, error) { - return ToInt(in) -} +func Int(in any) (int, error) { return ToInt(in) } // SafeInt convert value to int, will ignore error func SafeInt(in any) int { @@ -38,12 +98,10 @@ func SafeInt(in any) int { } // QuietInt convert value to int, will ignore error -func QuietInt(in any) int { - return SafeInt(in) -} +func QuietInt(in any) int { return SafeInt(in) } -// MustInt convert value to int, will panic on error -func MustInt(in any) int { +// IntOrPanic convert value to int, will panic on error +func IntOrPanic(in any) int { val, err := ToInt(in) if err != nil { panic(err) @@ -51,19 +109,15 @@ func MustInt(in any) int { return val } -// IntOrPanic convert value to int, will panic on error -func IntOrPanic(in any) int { - return MustInt(in) -} +// MustInt convert value to int, will panic on error +func MustInt(in any) int { return IntOrPanic(in) } // IntOrDefault convert value to int, return defaultVal on failed -func IntOrDefault(in any, defVal int) int { - return IntOr(in, defVal) -} +func IntOrDefault(in any, defVal int) int { return IntOr(in, defVal) } // IntOr convert value to int, return defaultVal on failed func IntOr(in any, defVal int) int { - val, err := ToIntWithFunc(in, nil) + val, err := ToIntWith(in) if err != nil { return defVal } @@ -71,20 +125,28 @@ func IntOr(in any, defVal int) int { } // IntOrErr convert value to int, return error on failed -func IntOrErr(in any) (iVal int, err error) { - return ToIntWithFunc(in, nil) -} +func IntOrErr(in any) (int, error) { return ToIntWith(in) } // ToInt convert value to int, return error on failed -func ToInt(in any) (iVal int, err error) { - return ToIntWithFunc(in, nil) -} +func ToInt(in any) (int, error) { return ToIntWith(in) } + +// ToIntWith convert value to int, can with some option func. +// +// Example: +// +// ToIntWithFunc(val, mathutil.WithNilAsFail, mathutil.WithUserConvFn(func(in any) (int, error) { +// }) +func ToIntWith(in any, optFns ...ConvOptionFn[int]) (iVal int, err error) { + opt := NewConvOption[int](optFns...) + if !opt.NilAsFail && in == nil { + return 0, nil + } -// ToIntWithFunc convert value to int, will call usrFn on value type not supported. -func ToIntWithFunc(in any, usrFn ToIntFunc) (iVal int, err error) { switch tVal := in.(type) { case int: iVal = tVal + case *int: // default support int ptr type + iVal = *tVal case int8: iVal = int(tVal) case int16: @@ -131,7 +193,7 @@ func ToIntWithFunc(in any, usrFn ToIntFunc) (iVal int, err error) { } case string: iVal, err = strconv.Atoi(strings.TrimSpace(tVal)) - case interface{ Int64() (int64, error) }: // eg: json.Number + case comdef.Int64able: // eg: json.Number var i64 int64 if i64, err = tVal.Int64(); err == nil { if i64 > math.MaxInt32 { @@ -141,11 +203,19 @@ func ToIntWithFunc(in any, usrFn ToIntFunc) (iVal int, err error) { } } default: - if usrFn != nil { - return usrFn(in) - } else { - err = comdef.ErrConvType + if opt.HandlePtr { + if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer { + rv = rv.Elem() + if checkfn.IsSimpleKind(rv.Kind()) { + return ToIntWith(rv.Interface(), optFns...) + } + } } + + if opt.UserConvFn != nil { + return opt.UserConvFn(in) + } + err = comdef.ErrConvType } return } @@ -165,29 +235,127 @@ func StrIntOr(s string, defVal int) int { return iVal } +/************************************************************* + * convert value to int64 + *************************************************************/ + +// Int64 convert value to int64, return error on failed +func Int64(in any) (int64, error) { return ToInt64(in) } + +// SafeInt64 convert value to int64, will ignore error +func SafeInt64(in any) int64 { + i64, _ := ToInt64With(in) + return i64 +} + +// QuietInt64 convert value to int64, will ignore error +func QuietInt64(in any) int64 { return SafeInt64(in) } + +// MustInt64 convert value to int64, will panic on error +func MustInt64(in any) int64 { + i64, err := ToInt64With(in) + if err != nil { + panic(err) + } + return i64 +} + +// Int64OrDefault convert value to int64, return default val on failed +func Int64OrDefault(in any, defVal int64) int64 { return Int64Or(in, defVal) } + +// Int64Or convert value to int64, return default val on failed +func Int64Or(in any, defVal int64) int64 { + i64, err := ToInt64With(in) + if err != nil { + return defVal + } + return i64 +} + +// ToInt64 convert value to int64, return error on failed +func ToInt64(in any) (int64, error) { return ToInt64With(in) } + +// Int64OrErr convert value to int64, return error on failed +func Int64OrErr(in any) (int64, error) { return ToInt64With(in) } + +// ToInt64With try to convert value to int64. can with some option func, more see ConvOption. +func ToInt64With(in any, optFns ...ConvOptionFn[int64]) (i64 int64, err error) { + opt := NewConvOption(optFns...) + if !opt.NilAsFail && in == nil { + return 0, nil + } + + switch tVal := in.(type) { + case string: + i64, err = strconv.ParseInt(strings.TrimSpace(tVal), 10, 0) + case int: + i64 = int64(tVal) + case int8: + i64 = int64(tVal) + case int16: + i64 = int64(tVal) + case int32: + i64 = int64(tVal) + case int64: + i64 = tVal + case *int64: // default support int64 ptr type + i64 = *tVal + case uint: + i64 = int64(tVal) + case uint8: + i64 = int64(tVal) + case uint16: + i64 = int64(tVal) + case uint32: + i64 = int64(tVal) + case uint64: + i64 = int64(tVal) + case float32: + i64 = int64(tVal) + case float64: + i64 = int64(tVal) + case time.Duration: + i64 = int64(tVal) + case comdef.Int64able: // eg: json.Number + i64, err = tVal.Int64() + default: + if opt.HandlePtr { + if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer { + rv = rv.Elem() + if checkfn.IsSimpleKind(rv.Kind()) { + return ToInt64With(rv.Interface(), optFns...) + } + } + } + + if opt.UserConvFn != nil { + i64, err = opt.UserConvFn(in) + } else { + err = comdef.ErrConvType + } + } + return +} + /************************************************************* * convert value to uint *************************************************************/ // Uint convert any to uint, return error on failed -func Uint(in any) (uint64, error) { - return ToUint(in) -} +func Uint(in any) (uint, error) { return ToUint(in) } // SafeUint convert any to uint, will ignore error -func SafeUint(in any) uint64 { +func SafeUint(in any) uint { val, _ := ToUint(in) return val } // QuietUint convert any to uint, will ignore error -func QuietUint(in any) uint64 { - return SafeUint(in) -} +func QuietUint(in any) uint { return SafeUint(in) } // MustUint convert any to uint, will panic on error -func MustUint(in any) uint64 { - val, err := ToUintWithFunc(in, nil) +func MustUint(in any) uint { + val, err := ToUintWith(in) if err != nil { panic(err) } @@ -195,13 +363,11 @@ func MustUint(in any) uint64 { } // UintOrDefault convert any to uint, return default val on failed -func UintOrDefault(in any, defVal uint64) uint64 { - return UintOr(in, defVal) -} +func UintOrDefault(in any, defVal uint) uint { return UintOr(in, defVal) } // UintOr convert any to uint, return default val on failed -func UintOr(in any, defVal uint64) uint64 { - val, err := ToUintWithFunc(in, nil) +func UintOr(in any, defVal uint) uint { + val, err := ToUintWith(in) if err != nil { return defVal } @@ -209,17 +375,124 @@ func UintOr(in any, defVal uint64) uint64 { } // UintOrErr convert value to uint, return error on failed -func UintOrErr(in any) (uint64, error) { - return ToUintWithFunc(in, nil) -} +func UintOrErr(in any) (uint, error) { return ToUintWith(in) } // ToUint convert value to uint, return error on failed -func ToUint(in any) (u64 uint64, err error) { - return ToUintWithFunc(in, nil) +func ToUint(in any) (u64 uint, err error) { return ToUintWith(in) } + +// ToUintWith try to convert value to uint. can with some option func, more see ConvOption. +func ToUintWith(in any, optFns ...ConvOptionFn[uint]) (uVal uint, err error) { + opt := NewConvOption(optFns...) + if !opt.NilAsFail && in == nil { + return 0, nil + } + + switch tVal := in.(type) { + case int: + uVal = uint(tVal) + case int8: + uVal = uint(tVal) + case int16: + uVal = uint(tVal) + case int32: + uVal = uint(tVal) + case int64: + uVal = uint(tVal) + case uint: + uVal = tVal + case *uint: // default support uint ptr type + uVal = *tVal + case uint8: + uVal = uint(tVal) + case uint16: + uVal = uint(tVal) + case uint32: + uVal = uint(tVal) + case uint64: + uVal = uint(tVal) + case float32: + uVal = uint(tVal) + case float64: + uVal = uint(tVal) + case time.Duration: + uVal = uint(tVal) + case comdef.Int64able: // eg: json.Number + var i64 int64 + i64, err = tVal.Int64() + uVal = uint(i64) + case string: + var u64 uint64 + u64, err = strconv.ParseUint(strings.TrimSpace(tVal), 10, 0) + uVal = uint(u64) + default: + if opt.HandlePtr { + if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer { + rv = rv.Elem() + if checkfn.IsSimpleKind(rv.Kind()) { + return ToUintWith(rv.Interface(), optFns...) + } + } + } + + if opt.UserConvFn != nil { + uVal, err = opt.UserConvFn(in) + } else { + err = comdef.ErrConvType + } + } + return } -// ToUintWithFunc convert value to uint, will call usrFn on value type not supported. -func ToUintWithFunc(in any, usrFn ToUintFunc) (u64 uint64, err error) { +/************************************************************* + * convert value to uint64 + *************************************************************/ + +// Uint64 convert any to uint64, return error on failed +func Uint64(in any) (uint64, error) { return ToUint64(in) } + +// QuietUint64 convert any to uint64, will ignore error +func QuietUint64(in any) uint64 { return SafeUint64(in) } + +// SafeUint64 convert any to uint64, will ignore error +func SafeUint64(in any) uint64 { + val, _ := ToUint64(in) + return val +} + +// MustUint64 convert any to uint64, will panic on error +func MustUint64(in any) uint64 { + val, err := ToUint64With(in) + if err != nil { + panic(err) + } + return val +} + +// Uint64OrDefault convert any to uint64, return default val on failed +func Uint64OrDefault(in any, defVal uint64) uint64 { return Uint64Or(in, defVal) } + +// Uint64Or convert any to uint64, return default val on failed +func Uint64Or(in any, defVal uint64) uint64 { + val, err := ToUint64With(in) + if err != nil { + return defVal + } + return val +} + +// Uint64OrErr convert value to uint64, return error on failed +func Uint64OrErr(in any) (uint64, error) { return ToUint64With(in) } + +// ToUint64 convert value to uint64, return error on failed +func ToUint64(in any) (uint64, error) { return ToUint64With(in) } + +// ToUint64With try to convert value to uint64. can with some option func, more see ConvOption. +func ToUint64With(in any, optFns ...ConvOptionFn[uint64]) (u64 uint64, err error) { + opt := NewConvOption(optFns...) + if !opt.NilAsFail && in == nil { + return 0, nil + } + switch tVal := in.(type) { case int: u64 = uint64(tVal) @@ -241,21 +514,32 @@ func ToUintWithFunc(in any, usrFn ToUintFunc) (u64 uint64, err error) { u64 = uint64(tVal) case uint64: u64 = tVal + case *uint64: // default support uint64 ptr type + u64 = *tVal case float32: u64 = uint64(tVal) case float64: u64 = uint64(tVal) case time.Duration: u64 = uint64(tVal) - case interface{ Int64() (int64, error) }: // eg: json.Number + case comdef.Int64able: // eg: json.Number var i64 int64 i64, err = tVal.Int64() u64 = uint64(i64) case string: u64, err = strconv.ParseUint(strings.TrimSpace(tVal), 10, 0) default: - if usrFn != nil { - u64, err = usrFn(in) + if opt.HandlePtr { + if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer { + rv = rv.Elem() + if checkfn.IsSimpleKind(rv.Kind()) { + return ToUint64With(rv.Interface(), optFns...) + } + } + } + + if opt.UserConvFn != nil { + u64, err = opt.UserConvFn(in) } else { err = comdef.ErrConvType } @@ -264,124 +548,24 @@ func ToUintWithFunc(in any, usrFn ToUintFunc) (u64 uint64, err error) { } /************************************************************* - * convert value to int64 - *************************************************************/ - -// Int64 convert value to int64, return error on failed -func Int64(in any) (int64, error) { - return ToInt64(in) -} - -// SafeInt64 convert value to int64, will ignore error -func SafeInt64(in any) int64 { - i64, _ := ToInt64WithFunc(in, nil) - return i64 -} - -// QuietInt64 convert value to int64, will ignore error -func QuietInt64(in any) int64 { - return SafeInt64(in) -} - -// MustInt64 convert value to int64, will panic on error -func MustInt64(in any) int64 { - i64, err := ToInt64WithFunc(in, nil) - if err != nil { - panic(err) - } - return i64 -} - -// Int64OrDefault convert value to int64, return default val on failed -func Int64OrDefault(in any, defVal int64) int64 { - return Int64Or(in, defVal) -} - -// Int64Or convert value to int64, return default val on failed -func Int64Or(in any, defVal int64) int64 { - i64, err := ToInt64WithFunc(in, nil) - if err != nil { - return defVal - } - return i64 -} - -// Int64OrErr convert value to int64, return error on failed -func Int64OrErr(in any) (int64, error) { - return ToInt64(in) -} - -// ToInt64 convert value to int64, return error on failed -func ToInt64(in any) (i64 int64, err error) { - return ToInt64WithFunc(in, nil) -} - -// ToInt64WithFunc convert value to int64, will call usrFn on value type not supported. -func ToInt64WithFunc(in any, usrFn ToInt64Func) (i64 int64, err error) { - switch tVal := in.(type) { - case string: - i64, err = strconv.ParseInt(strings.TrimSpace(tVal), 10, 0) - case int: - i64 = int64(tVal) - case int8: - i64 = int64(tVal) - case int16: - i64 = int64(tVal) - case int32: - i64 = int64(tVal) - case int64: - i64 = tVal - case uint: - i64 = int64(tVal) - case uint8: - i64 = int64(tVal) - case uint16: - i64 = int64(tVal) - case uint32: - i64 = int64(tVal) - case uint64: - i64 = int64(tVal) - case float32: - i64 = int64(tVal) - case float64: - i64 = int64(tVal) - case time.Duration: - i64 = int64(tVal) - case interface{ Int64() (int64, error) }: // eg: json.Number - i64, err = tVal.Int64() - default: - if usrFn != nil { - i64, err = usrFn(in) - } else { - err = comdef.ErrConvType - } - } - return -} - -/************************************************************* - * convert value to float + * convert value to float64 *************************************************************/ // QuietFloat convert value to float64, will ignore error. alias of SafeFloat -func QuietFloat(in any) float64 { - return SafeFloat(in) -} +func QuietFloat(in any) float64 { return SafeFloat(in) } // SafeFloat convert value to float64, will ignore error func SafeFloat(in any) float64 { - val, _ := ToFloatWithFunc(in, nil) + val, _ := ToFloatWith(in) return val } // FloatOrPanic convert value to float64, will panic on error -func FloatOrPanic(in any) float64 { - return MustFloat(in) -} +func FloatOrPanic(in any) float64 { return MustFloat(in) } // MustFloat convert value to float64, will panic on error func MustFloat(in any) float64 { - val, err := ToFloatWithFunc(in, nil) + val, err := ToFloatWith(in) if err != nil { panic(err) } @@ -389,13 +573,11 @@ func MustFloat(in any) float64 { } // FloatOrDefault convert value to float64, will return default value on error -func FloatOrDefault(in any, defVal float64) float64 { - return FloatOr(in, defVal) -} +func FloatOrDefault(in any, defVal float64) float64 { return FloatOr(in, defVal) } // FloatOr convert value to float64, will return default value on error func FloatOr(in any, defVal float64) float64 { - val, err := ToFloatWithFunc(in, nil) + val, err := ToFloatWith(in) if err != nil { return defVal } @@ -403,22 +585,21 @@ func FloatOr(in any, defVal float64) float64 { } // Float convert value to float64, return error on failed -func Float(in any) (float64, error) { - return ToFloatWithFunc(in, nil) -} +func Float(in any) (float64, error) { return ToFloatWith(in) } // FloatOrErr convert value to float64, return error on failed -func FloatOrErr(in any) (float64, error) { - return ToFloatWithFunc(in, nil) -} +func FloatOrErr(in any) (float64, error) { return ToFloatWith(in) } // ToFloat convert value to float64, return error on failed -func ToFloat(in any) (f64 float64, err error) { - return ToFloatWithFunc(in, nil) -} +func ToFloat(in any) (float64, error) { return ToFloatWith(in) } + +// ToFloatWith try to convert value to float64. can with some option func, more see ConvOption. +func ToFloatWith(in any, optFns ...ConvOptionFn[float64]) (f64 float64, err error) { + opt := NewConvOption(optFns...) + if !opt.NilAsFail && in == nil { + return 0, nil + } -// ToFloatWithFunc convert value to float64, will call usrFn if value type not supported. -func ToFloatWithFunc(in any, usrFn ToFloatFunc) (f64 float64, err error) { switch tVal := in.(type) { case string: f64, err = strconv.ParseFloat(strings.TrimSpace(tVal), 64) @@ -446,13 +627,24 @@ func ToFloatWithFunc(in any, usrFn ToFloatFunc) (f64 float64, err error) { f64 = float64(tVal) case float64: f64 = tVal + case *float64: // default support float64 ptr type + f64 = *tVal case time.Duration: f64 = float64(tVal) - case interface{ Float64() (float64, error) }: // eg: json.Number + case comdef.Float64able: // eg: json.Number f64, err = tVal.Float64() default: - if usrFn != nil { - f64, err = usrFn(in) + if opt.HandlePtr { + if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer { + rv = rv.Elem() + if checkfn.IsSimpleKind(rv.Kind()) { + return ToFloatWith(rv.Interface(), optFns...) + } + } + } + + if opt.UserConvFn != nil { + f64, err = opt.UserConvFn(in) } else { err = comdef.ErrConvType } @@ -466,7 +658,7 @@ func ToFloatWithFunc(in any, usrFn ToFloatFunc) (f64 float64, err error) { // MustString convert intX/floatX value to string, will panic on error func MustString(val any) string { - str, err := ToStringWithFunc(val, nil) + str, err := ToStringWith(val) if err != nil { panic(err) } @@ -477,13 +669,11 @@ func MustString(val any) string { func StringOrPanic(val any) string { return MustString(val) } // StringOrDefault convert intX/floatX value to string, will return default value on error -func StringOrDefault(val any, defVal string) string { - return StringOr(val, defVal) -} +func StringOrDefault(val any, defVal string) string { return StringOr(val, defVal) } // StringOr convert intX/floatX value to string, will return default value on error func StringOr(val any, defVal string) string { - str, err := ToStringWithFunc(val, nil) + str, err := ToStringWith(val) if err != nil { return defVal } @@ -491,19 +681,13 @@ func StringOr(val any, defVal string) string { } // ToString convert intX/floatX value to string, return error on failed -func ToString(val any) (string, error) { - return ToStringWithFunc(val, nil) -} +func ToString(val any) (string, error) { return ToStringWith(val) } // StringOrErr convert intX/floatX value to string, return error on failed -func StringOrErr(val any) (string, error) { - return ToStringWithFunc(val, nil) -} +func StringOrErr(val any) (string, error) { return ToStringWith(val) } // QuietString convert intX/floatX value to string, other type convert by fmt.Sprint -func QuietString(val any) string { - return SafeString(val) -} +func QuietString(val any) string { return SafeString(val) } // String convert intX/floatX value to string, other type convert by fmt.Sprint func String(val any) string { @@ -520,76 +704,15 @@ func SafeString(val any) string { // TryToString try convert intX/floatX value to string // // if defaultAsErr is False, will use fmt.Sprint convert other type -func TryToString(val any, defaultAsErr bool) (str string, err error) { - var usrFn comdef.ToStringFunc +func TryToString(val any, defaultAsErr bool) (string, error) { + var optFn comfunc.ConvOptionFn if !defaultAsErr { - usrFn = func(v any) (string, error) { - if val == nil { - return "", nil - } - return fmt.Sprint(v), nil - } + optFn = comfunc.WithUserConvFn(comfunc.StrBySprintFn) } - - return ToStringWithFunc(val, usrFn) + return ToStringWith(val, optFn) } -// ToStringWithFunc try convert intX/floatX value to string, will call usrFn if value type not supported. -// -// if defaultAsErr is False, will use fmt.Sprint convert other type -func ToStringWithFunc(val any, usrFn comdef.ToStringFunc) (str string, err error) { - switch value := val.(type) { - case int: - str = strconv.Itoa(value) - case int8: - str = strconv.Itoa(int(value)) - case int16: - str = strconv.Itoa(int(value)) - case int32: // same as `rune` - str = strconv.Itoa(int(value)) - case int64: - str = strconv.FormatInt(value, 10) - case uint: - str = strconv.FormatUint(uint64(value), 10) - case uint8: - str = strconv.FormatUint(uint64(value), 10) - case uint16: - str = strconv.FormatUint(uint64(value), 10) - case uint32: - str = strconv.FormatUint(uint64(value), 10) - case uint64: - str = strconv.FormatUint(value, 10) - case float32: - str = strconv.FormatFloat(float64(value), 'f', -1, 32) - case float64: - str = strconv.FormatFloat(value, 'f', -1, 64) - case time.Duration: - str = strconv.FormatInt(int64(value), 10) - case string: - str = value - case fmt.Stringer: - str = value.String() - default: - if usrFn != nil { - str, err = usrFn(val) - } else { - err = comdef.ErrConvType - } - } - return -} - -// Percent returns a values percent of the total -func Percent(val, total int) float64 { - if total == 0 { - return float64(0) - } - return (float64(val) / float64(total)) * 100 -} - -// ElapsedTime calc elapsed time 计算运行时间消耗 单位 ms(毫秒) -// -// Deprecated: use timex.ElapsedTime() -func ElapsedTime(startTime time.Time) string { - return fmt.Sprintf("%.3f", time.Since(startTime).Seconds()*1000) +// ToStringWith try to convert value to string. can with some option func, more see comfunc.ConvOption. +func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error) { + return comfunc.ToStringWith(in, optFns...) } diff --git a/vendor/github.com/gookit/goutil/mathutil/mathutil.go b/vendor/github.com/gookit/goutil/mathutil/mathutil.go index 1b47f32a9f..4831ceb1d3 100644 --- a/vendor/github.com/gookit/goutil/mathutil/mathutil.go +++ b/vendor/github.com/gookit/goutil/mathutil/mathutil.go @@ -2,6 +2,8 @@ package mathutil import ( + "math" + "github.com/gookit/goutil/comdef" ) @@ -71,3 +73,37 @@ func GteOr[T comdef.XintOrFloat](val, min, defVal T) T { } return defVal } + +// Mul computes the a*b value, rounding the result. +func Mul[T1, T2 comdef.XintOrFloat](a T1, b T2) float64 { + return math.Round(SafeFloat(a) * SafeFloat(b)) +} + +// MulF2i computes the float64 type a * b value, rounding the result to an integer. +func MulF2i(a, b float64) int { + return int(math.Round(a * b)) +} + +// Div computes the a/b value, result use round handle. +func Div[T1, T2 comdef.XintOrFloat](a T1, b T2) float64 { + return math.Round(SafeFloat(a) / SafeFloat(b)) +} + +// DivInt computes the int type a / b value, rounding the result to an integer. +func DivInt[T comdef.Integer](a, b T) int { + fv := math.Round(float64(a) / float64(b)) + return int(fv) +} + +// DivF2i computes the float64 type a / b value, rounding the result to an integer. +func DivF2i(a, b float64) int { + return int(math.Round(a / b)) +} + +// Percent returns a values percent of the total +func Percent(val, total int) float64 { + if total == 0 { + return float64(0) + } + return (float64(val) / float64(total)) * 100 +} diff --git a/vendor/github.com/gookit/goutil/reflects/check.go b/vendor/github.com/gookit/goutil/reflects/check.go index 062ce6bc5c..8132960fe1 100644 --- a/vendor/github.com/gookit/goutil/reflects/check.go +++ b/vendor/github.com/gookit/goutil/reflects/check.go @@ -10,8 +10,9 @@ func HasChild(v reflect.Value) bool { switch v.Kind() { case reflect.Array, reflect.Slice, reflect.Map, reflect.Struct: return true + default: + return false } - return false } // IsArrayOrSlice check. eg: array, slice @@ -122,9 +123,9 @@ func IsEmpty(v reflect.Value) bool { return v.Float() == 0 case reflect.Interface, reflect.Ptr, reflect.Func: return v.IsNil() + default: + return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) } - - return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) } // IsEmptyValue reflect value check, alias of the IsEmptyReal() @@ -158,7 +159,7 @@ func IsEmptyReal(v reflect.Value) bool { return v.IsNil() case reflect.Invalid: return true + default: + return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) } - - return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) } diff --git a/vendor/github.com/gookit/goutil/reflects/conv.go b/vendor/github.com/gookit/goutil/reflects/conv.go index f5376ec41a..c95dcfe212 100644 --- a/vendor/github.com/gookit/goutil/reflects/conv.go +++ b/vendor/github.com/gookit/goutil/reflects/conv.go @@ -126,12 +126,12 @@ func ConvToKind(val any, kind reflect.Kind) (rv reflect.Value, err error) { rv = reflect.ValueOf(dstV) } case reflect.Uint: - var dstV uint64 + var dstV uint if dstV, err = mathutil.ToUint(val); err == nil { - rv = reflect.ValueOf(uint(dstV)) + rv = reflect.ValueOf(dstV) } case reflect.Uint8: - var dstV uint64 + var dstV uint if dstV, err = mathutil.ToUint(val); err == nil { if dstV > math.MaxUint8 { return rv, fmt.Errorf("value overflow uint8. val: %v", val) @@ -139,7 +139,7 @@ func ConvToKind(val any, kind reflect.Kind) (rv reflect.Value, err error) { rv = reflect.ValueOf(uint8(dstV)) } case reflect.Uint16: - var dstV uint64 + var dstV uint if dstV, err = mathutil.ToUint(val); err == nil { if dstV > math.MaxUint16 { return rv, fmt.Errorf("value overflow uint16. val: %v", val) @@ -147,7 +147,7 @@ func ConvToKind(val any, kind reflect.Kind) (rv reflect.Value, err error) { rv = reflect.ValueOf(uint16(dstV)) } case reflect.Uint32: - var dstV uint64 + var dstV uint if dstV, err = mathutil.ToUint(val); err == nil { if dstV > math.MaxUint32 { return rv, fmt.Errorf("value overflow uint32. val: %v", val) @@ -156,7 +156,7 @@ func ConvToKind(val any, kind reflect.Kind) (rv reflect.Value, err error) { } case reflect.Uint64: var dstV uint64 - if dstV, err = mathutil.ToUint(val); err == nil { + if dstV, err = mathutil.ToUint64(val); err == nil { rv = reflect.ValueOf(dstV) } case reflect.Float32: diff --git a/vendor/github.com/gookit/goutil/reflects/reflects.go b/vendor/github.com/gookit/goutil/reflects/reflects.go index cd2ea0eb55..0a6cdde8a4 100644 --- a/vendor/github.com/gookit/goutil/reflects/reflects.go +++ b/vendor/github.com/gookit/goutil/reflects/reflects.go @@ -2,7 +2,6 @@ package reflects import ( - "fmt" "reflect" ) @@ -12,6 +11,6 @@ var ( anyType = reflect.TypeOf((*any)(nil)).Elem() errorType = reflect.TypeOf((*error)(nil)).Elem() - fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() + // fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() reflectValueType = reflect.TypeOf((*reflect.Value)(nil)).Elem() ) diff --git a/vendor/github.com/gookit/goutil/structs/writer.go b/vendor/github.com/gookit/goutil/structs/writer.go index ac306e1100..dde4bcad95 100644 --- a/vendor/github.com/gookit/goutil/structs/writer.go +++ b/vendor/github.com/gookit/goutil/structs/writer.go @@ -4,9 +4,12 @@ import ( "errors" "fmt" "reflect" + "time" + "github.com/gookit/goutil/comdef" "github.com/gookit/goutil/maputil" "github.com/gookit/goutil/reflects" + "github.com/gookit/goutil/strutil" ) // NewWriter create a struct writer @@ -46,6 +49,9 @@ type SetOptions struct { // // default: false ParseDefaultEnv bool + + // StopOnError if true, will stop set value on error happened. default: false + // StopOnError bool } // WithParseDefault value by tag "default" @@ -85,6 +91,7 @@ func setValues(rv reflect.Value, data map[string]any, opt *SetOptions) error { return nil } + var es comdef.Errors rt := rv.Type() for i := 0; i < rt.NumField(); i++ { @@ -100,7 +107,8 @@ func setValues(rv reflect.Value, data map[string]any, opt *SetOptions) error { if ok { info, err := ParseTagValueDefault(name, tagVal) if err != nil { - return err + es = append(es, err) + continue } name = info.Get("name") } @@ -112,7 +120,7 @@ func setValues(rv reflect.Value, data map[string]any, opt *SetOptions) error { if !ok && opt.ParseDefault && fv.IsZero() { defVal := ft.Tag.Get(opt.DefaultValTag) if err := initDefaultValue(fv, defVal, opt.ParseDefaultEnv); err != nil { - return err + es = append(es, err) } continue } @@ -127,22 +135,39 @@ func setValues(rv reflect.Value, data map[string]any, opt *SetOptions) error { // field is struct if fv.Kind() == reflect.Struct { - asMp, err := maputil.TryAnyMap(val) - if err != nil { - return fmt.Errorf("must provide map data for field %q, err=%v", ft.Name, err) + // up: special handle time.Time struct + if _, ok := fv.Interface().(time.Time); ok { + tm, er := strutil.ToTime(strutil.StringOr(val, "")) + if er != nil { + es = append(es, er) + continue + } + if er = reflects.SetValue(fv, tm); er != nil { + es = append(es, er) + } + continue } - if err := setValues(fv, asMp, opt); err != nil { - return err + asMp, err := maputil.TryAnyMap(val) + if err != nil { + err = fmt.Errorf("must provide map for set struct field %q, err=%v", ft.Name, err) + es = append(es, err) + continue + } + + // recursive processing sub-struct + if err = setValues(fv, asMp, opt); err != nil { + es = append(es, err) } continue } // set field value if err := reflects.SetValue(fv, val); err != nil { - return err + es = append(es, err) + continue } } - return nil + return es.ErrOrNil() } diff --git a/vendor/github.com/gookit/goutil/strutil/convert.go b/vendor/github.com/gookit/goutil/strutil/convert.go index 71ed78a610..c77615d179 100644 --- a/vendor/github.com/gookit/goutil/strutil/convert.go +++ b/vendor/github.com/gookit/goutil/strutil/convert.go @@ -2,7 +2,6 @@ package strutil import ( "errors" - "fmt" "reflect" "regexp" "strconv" @@ -10,7 +9,6 @@ import ( "time" "unsafe" - "github.com/gookit/goutil/comdef" "github.com/gookit/goutil/internal/comfunc" "github.com/gookit/goutil/mathutil" ) @@ -91,39 +89,29 @@ func Implode(sep string, ss ...string) string { return strings.Join(ss, sep) } *************************************************************/ // String convert value to string, return error on failed -func String(val any) (string, error) { - return ToStringWithFunc(val, nil) -} +func String(val any) (string, error) { return ToStringWith(val) } // ToString convert value to string, return error on failed -func ToString(val any) (string, error) { - return ToStringWithFunc(val, nil) -} +func ToString(val any) (string, error) { return ToStringWith(val) } // StringOrErr convert value to string, return error on failed -func StringOrErr(val any) (string, error) { - return ToStringWithFunc(val, nil) -} +func StringOrErr(val any) (string, error) { return ToStringWith(val) } // QuietString convert value to string, will ignore error. same as SafeString() -func QuietString(val any) string { - return SafeString(val) -} +func QuietString(val any) string { return SafeString(val) } // SafeString convert value to string, will ignore error func SafeString(in any) string { - val, _ := ToStringWithFunc(in, SprintToStrFunc) - return val + s, _ := AnyToString(in, false) + return s } // StringOrPanic convert value to string, will panic on error -func StringOrPanic(val any) string { - return MustString(val) -} +func StringOrPanic(val any) string { return MustString(val) } // MustString convert value to string, will panic on error func MustString(val any) string { - s, err := ToStringWithFunc(val, nil) + s, err := ToStringWith(val) if err != nil { panic(err) } @@ -131,93 +119,34 @@ func MustString(val any) string { } // StringOrDefault convert any value to string, return default value on failed -func StringOrDefault(val any, defVal string) string { - return StringOr(val, defVal) -} +func StringOrDefault(val any, defVal string) string { return StringOr(val, defVal) } // StringOr convert any value to string, return default value on failed func StringOr(val any, defVal string) string { - s, err := ToStringWithFunc(val, nil) + s, err := ToStringWith(val) if err != nil { return defVal } return s } -// SprintToStrFunc convert any value to string by fmt.Sprint -var SprintToStrFunc = func(v any) (string, error) { - if v == nil { - return "", nil - } - return fmt.Sprint(v), nil -} - // AnyToString convert any value to string. // // For defaultAsErr: // -// - False will use fmt.Sprint convert complex type -// - True will return error on fail. +// - False will use fmt.Sprint convert unsupported type +// - True will return error on convert fail. func AnyToString(val any, defaultAsErr bool) (s string, err error) { - var fbFunc comdef.ToStringFunc + var optFn comfunc.ConvOptionFn if !defaultAsErr { - fbFunc = SprintToStrFunc + optFn = comfunc.WithUserConvFn(comfunc.StrBySprintFn) } - - return ToStringWithFunc(val, fbFunc) + return ToStringWith(val, optFn) } -// ToStringWithFunc convert value to string, with a func to fallback handle. -// -// On not convert: -// - If fbFn is nil, will return comdef.ErrConvType. -// - If fbFn is not nil, will call it to convert. -func ToStringWithFunc(val any, fbFn comdef.ToStringFunc) (str string, err error) { - switch value := val.(type) { - case int: - str = strconv.Itoa(value) - case int8: - str = strconv.Itoa(int(value)) - case int16: - str = strconv.Itoa(int(value)) - case int32: // same as `rune` - str = strconv.Itoa(int(value)) - case int64: - str = strconv.FormatInt(value, 10) - case uint: - str = strconv.FormatUint(uint64(value), 10) - case uint8: - str = strconv.FormatUint(uint64(value), 10) - case uint16: - str = strconv.FormatUint(uint64(value), 10) - case uint32: - str = strconv.FormatUint(uint64(value), 10) - case uint64: - str = strconv.FormatUint(value, 10) - case float32: - str = strconv.FormatFloat(float64(value), 'f', -1, 32) - case float64: - str = strconv.FormatFloat(value, 'f', -1, 64) - case bool: - str = strconv.FormatBool(value) - case string: - str = value - case []byte: - str = string(value) - case time.Duration: - str = strconv.FormatInt(int64(value), 10) - case fmt.Stringer: - str = value.String() - case error: - str = value.Error() - default: - if fbFn == nil { - err = comdef.ErrConvType - } else { - str, err = fbFn(value) - } - } - return +// ToStringWith try to convert value to string. can with some option func, more see comfunc.ConvOption. +func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error) { + return comfunc.ToStringWith(in, optFns...) } /************************************************************* @@ -230,9 +159,7 @@ func ToBool(s string) (bool, error) { } // QuietBool convert to bool, will ignore error -func QuietBool(s string) bool { - return SafeBool(s) -} +func QuietBool(s string) bool { return SafeBool(s) } // SafeBool convert to bool, will ignore error func SafeBool(s string) bool { @@ -289,14 +216,10 @@ func SafeInt(s string) int { } // QuietInt convert string to int, will ignore error -func QuietInt(s string) int { - return SafeInt(s) -} +func QuietInt(s string) int { return SafeInt(s) } // MustInt convert string to int, will panic on error -func MustInt(s string) int { - return IntOrPanic(s) -} +func MustInt(s string) int { return IntOrPanic(s) } // IntOrPanic convert value to int, will panic on error func IntOrPanic(s string) int { @@ -312,10 +235,10 @@ func IntOrPanic(s string) int { *************************************************************/ // Int64 convert string to int, will ignore error -func Int64(s string) int64 { - val, _ := Int64OrErr(s) - return val -} +func Int64(s string) int64 { return SafeInt64(s) } + +// QuietInt64 convert string to int, will ignore error +func QuietInt64(s string) int64 { return SafeInt64(s) } // SafeInt64 convert string to int, will ignore error func SafeInt64(s string) int64 { @@ -323,11 +246,6 @@ func SafeInt64(s string) int64 { return val } -// QuietInt64 convert string to int, will ignore error -func QuietInt64(s string) int64 { - return SafeInt64(s) -} - // ToInt64 convert string to int, return error on fail func ToInt64(s string) (int64, error) { return strconv.ParseInt(s, 10, 0) @@ -353,9 +271,7 @@ func Int64OrErr(s string) (int64, error) { } // MustInt64 convert value to int, will panic on error -func MustInt64(s string) int64 { - return Int64OrPanic(s) -} +func MustInt64(s string) int64 { return Int64OrPanic(s) } // Int64OrPanic convert value to int, will panic on error func Int64OrPanic(s string) int64 { @@ -371,10 +287,7 @@ func Int64OrPanic(s string) int64 { *************************************************************/ // Uint convert string to uint, will ignore error -func Uint(s string) uint64 { - val, _ := UintOrErr(s) - return val -} +func Uint(s string) uint64 { return SafeUint(s) } // SafeUint convert string to uint, will ignore error func SafeUint(s string) uint64 { @@ -393,9 +306,7 @@ func UintOrErr(s string) (uint64, error) { } // MustUint convert value to uint, will panic on error. alias of UintOrPanic() -func MustUint(s string) uint64 { - return UintOrPanic(s) -} +func MustUint(s string) uint64 { return UintOrPanic(s) } // UintOrPanic convert value to uint, will panic on error func UintOrPanic(s string) uint64 { diff --git a/vendor/github.com/gookit/goutil/strutil/strutil.go b/vendor/github.com/gookit/goutil/strutil/strutil.go index e81253f90d..7a2ca434b1 100644 --- a/vendor/github.com/gookit/goutil/strutil/strutil.go +++ b/vendor/github.com/gookit/goutil/strutil/strutil.go @@ -2,12 +2,9 @@ package strutil import ( - "bytes" - "encoding/json" "errors" "fmt" "strings" - "text/template" "github.com/gookit/goutil/comdef" ) @@ -92,68 +89,6 @@ func NewReplacer(pairs map[string]string) *strings.Replacer { return strings.NewReplacer(ss...) } -// PrettyJSON get pretty Json string -// Deprecated: please use fmtutil.PrettyJSON() or jsonutil.Pretty() instead it -func PrettyJSON(v any) (string, error) { - out, err := json.MarshalIndent(v, "", " ") - return string(out), err -} - -var builtInFuncs = template.FuncMap{ - // don't escape content - "raw": func(s string) string { - return s - }, - "trim": func(s string) string { - return strings.TrimSpace(s) - }, - // join strings - "join": func(ss []string, sep string) string { - return strings.Join(ss, sep) - }, - // lower first char - "lcFirst": func(s string) string { - return LowerFirst(s) - }, - // upper first char - "upFirst": func(s string) string { - return UpperFirst(s) - }, -} - -// RenderTemplate quickly render text template. -// -// Deprecated: please use textutil.RenderTpl() instead it -func RenderTemplate(input string, data any, fns template.FuncMap, isFile ...bool) string { - return RenderText(input, data, fns, isFile...) -} - -// RenderText quickly render text template -// -// Deprecated: please use textutil.RenderTpl() instead it -func RenderText(input string, data any, fns template.FuncMap, isFile ...bool) string { - t := template.New("simple-text") - t.Funcs(builtInFuncs) - - // add custom template functions - if len(fns) > 0 { - t.Funcs(fns) - } - - if len(isFile) > 0 && isFile[0] { - template.Must(t.ParseFiles(input)) - } else { - template.Must(t.Parse(input)) - } - - // use buffer receive rendered content - buf := new(bytes.Buffer) - if err := t.Execute(buf, data); err != nil { - panic(err) - } - return buf.String() -} - // WrapTag for given string. func WrapTag(s, tag string) string { if s == "" { diff --git a/vendor/modules.txt b/vendor/modules.txt index 01f00a5f0d..82cf397d99 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1107,11 +1107,11 @@ github.com/google/uuid # github.com/gookit/color v1.5.4 ## explicit; go 1.18 github.com/gookit/color -# github.com/gookit/config/v2 v2.2.4 +# github.com/gookit/config/v2 v2.2.5 ## explicit; go 1.19 github.com/gookit/config/v2 github.com/gookit/config/v2/yaml -# github.com/gookit/goutil v0.6.14 +# github.com/gookit/goutil v0.6.15 ## explicit; go 1.19 github.com/gookit/goutil github.com/gookit/goutil/arrutil