From 9db34ad482a972956d9281e4db017ea58a8b54cd Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Tue, 14 Jan 2025 18:42:29 +0300 Subject: [PATCH 1/2] options: generic options funcs Signed-off-by: Vasiliy Tolstov --- go.mod | 1 + go.sum | 4 + options/options.go | 222 ++++++++++++++++ options/options_test.go | 181 +++++++++++++ options/util.go | 577 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 985 insertions(+) create mode 100644 options/options.go create mode 100644 options/options_test.go create mode 100644 options/util.go diff --git a/go.mod b/go.mod index 6af8b0b9..27a187c0 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/matoous/go-nanoid v1.5.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 + github.com/spf13/cast v1.7.1 go.uber.org/automaxprocs v1.6.0 go.unistack.org/micro-proto/v3 v3.4.1 golang.org/x/sync v0.10.0 diff --git a/go.sum b/go.sum index 72be286c..e6bf16bc 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -68,6 +70,8 @@ github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 h1:G/FZtUu7a6NTWl3KUHMV9 github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= diff --git a/options/options.go b/options/options.go new file mode 100644 index 00000000..e6f67470 --- /dev/null +++ b/options/options.go @@ -0,0 +1,222 @@ +package options + +import ( + "reflect" + "strings" + "time" + + "github.com/spf13/cast" + mreflect "go.unistack.org/micro/v3/util/reflect" +) + +// Options interface must be used by all options +type Validator interface { + // Validate returns nil, if all options are correct, + // otherwise returns an error explaining the mistake + Validate() error +} + +// Option func signature +type Option func(interface{}) error + +// Apply assign options to struct src +func Apply(src interface{}, opts ...Option) error { + for _, opt := range opts { + if err := opt(src); err != nil { + return err + } + } + return nil +} + +// SetValueByPath set src struct field to val dst via path +func SetValueByPath(src interface{}, dst interface{}, path string) error { + var err error + + switch v := dst.(type) { + case []interface{}: + if len(v) == 1 { + dst = v[0] + } + } + + var sv reflect.Value + switch t := src.(type) { + case reflect.Value: + sv = t + default: + sv = reflect.ValueOf(src) + } + + parts := strings.Split(path, ".") + + for _, p := range parts { + + if sv.Kind() == reflect.Ptr { + sv = sv.Elem() + } + if sv.Kind() != reflect.Struct { + return mreflect.ErrInvalidStruct + } + + typ := sv.Type() + for idx := 0; idx < typ.NumField(); idx++ { + fld := typ.Field(idx) + val := sv.Field(idx) + + /* + if len(fld.PkgPath) != 0 { + continue + } + */ + + if fld.Anonymous { + if len(parts) == 1 && val.Kind() == reflect.Struct { + if err = SetValueByPath(val, dst, p); err != nil { + return err + } + } + } + + if fld.Name != p && !strings.EqualFold(strings.ToLower(fld.Name), strings.ToLower(p)) { + continue + } + + switch val.Interface().(type) { + case []time.Duration: + dst, err = cast.ToDurationSliceE(dst) + if err != nil { + return err + } + reflect.Copy(val, reflect.ValueOf(dst)) + return nil + case time.Duration: + dst, err = cast.ToDurationE(dst) + if err != nil { + return err + } + val.Set(reflect.ValueOf(dst)) + return nil + case time.Time: + dst, err = cast.ToTimeE(dst) + if err != nil { + return err + } + val.Set(reflect.ValueOf(dst)) + return nil + } + + switch val.Kind() { + case reflect.Map: + if val.IsZero() { + val.Set(reflect.MakeMap(val.Type())) + } + + return setMap(val.Interface(), dst) + case reflect.Array, reflect.Slice: + switch val.Type().Elem().Kind() { + case reflect.Bool: + dst, err = cast.ToBoolSliceE(dst) + case reflect.String: + dst, err = cast.ToStringSliceE(dst) + case reflect.Float32: + dst, err = toFloat32SliceE(dst) + case reflect.Float64: + dst, err = toFloat64SliceE(dst) + case reflect.Int8: + dst, err = toInt8SliceE(dst) + case reflect.Int: + dst, err = cast.ToIntSliceE(dst) + case reflect.Int16: + dst, err = toInt16SliceE(dst) + case reflect.Int32: + dst, err = toInt32SliceE(dst) + case reflect.Int64: + dst, err = toInt64SliceE(dst) + case reflect.Uint8: + dst, err = toUint8SliceE(dst) + case reflect.Uint: + dst, err = toUintSliceE(dst) + case reflect.Uint16: + dst, err = toUint16SliceE(dst) + case reflect.Uint32: + dst, err = toUint32SliceE(dst) + case reflect.Uint64: + dst, err = toUint64SliceE(dst) + } + if err != nil { + return err + } + if val.Kind() == reflect.Slice { + val.Set(reflect.ValueOf(dst)) + } else { + reflect.Copy(val, reflect.ValueOf(dst)) + } + return nil + case reflect.Float32: + dst, err = toFloat32SliceE(dst) + case reflect.Float64: + dst, err = toFloat64SliceE(dst) + case reflect.Bool: + dst, err = cast.ToBoolE(dst) + case reflect.String: + dst, err = cast.ToStringE(dst) + case reflect.Int8: + dst, err = cast.ToInt8E(dst) + case reflect.Int: + dst, err = cast.ToIntE(dst) + case reflect.Int16: + dst, err = cast.ToInt16E(dst) + case reflect.Int32: + dst, err = cast.ToInt32E(dst) + case reflect.Int64: + dst, err = cast.ToInt64E(dst) + case reflect.Uint8: + dst, err = cast.ToUint8E(dst) + case reflect.Uint: + dst, err = cast.ToUintE(dst) + case reflect.Uint16: + dst, err = cast.ToUint16E(dst) + case reflect.Uint32: + dst, err = cast.ToUint32E(dst) + case reflect.Uint64: + dst, err = cast.ToUint64E(dst) + default: + } + if err != nil { + return err + } + val.Set(reflect.ValueOf(dst)) + } + } + + return nil +} + +// NewOption create new option with name +func NewOption(name string) func(...interface{}) Option { + return func(dst ...interface{}) Option { + return func(src interface{}) error { + return SetValueByPath(src, dst, name) + } + } +} + +var ( + Address = NewOption("Address") + Name = NewOption("Name") + Broker = NewOption("Broker") + Logger = NewOption("Logger") + Meter = NewOption("Meter") + Tracer = NewOption("Tracer") + Store = NewOption("Store") + Register = NewOption("Register") + Router = NewOption("Router") + Codec = NewOption("Codec") + Codecs = NewOption("Codecs") + Client = NewOption("Client") + Context = NewOption("Context") + TLSConfig = NewOption("TLSConfig") + Metadata = NewOption("Metadata") + Timeout = NewOption("Timeout") +) diff --git a/options/options_test.go b/options/options_test.go new file mode 100644 index 00000000..eed5050c --- /dev/null +++ b/options/options_test.go @@ -0,0 +1,181 @@ +package options_test + +import ( + "crypto/tls" + "sync" + "testing" + + "go.unistack.org/micro/v3/options" +) + +type codec interface { + Marshal(v interface{}, opts ...options.Option) ([]byte, error) + Unmarshal(b []byte, v interface{}, opts ...options.Option) error + String() string +} + +func TestCodecs(t *testing.T) { + type s struct { + Codecs map[string]codec + } + + wg := &sync.WaitGroup{} + tc := &tls.Config{InsecureSkipVerify: true} + opts := []options.Option{ + options.NewOption("Codecs")(wg), + options.NewOption("TLSConfig")(tc), + } + + src := &s{} + + if err := options.Apply(src, opts...); err != nil { + t.Fatal(err) + } +} + +func TestSpecial(t *testing.T) { + type s struct { + Wait *sync.WaitGroup + TLSConfig *tls.Config + } + + wg := &sync.WaitGroup{} + tc := &tls.Config{InsecureSkipVerify: true} + opts := []options.Option{ + options.NewOption("Wait")(wg), + options.NewOption("TLSConfig")(tc), + } + + src := &s{} + + if err := options.Apply(src, opts...); err != nil { + t.Fatal(err) + } + + if src.Wait == nil { + t.Fatalf("failed to set Wait %#+v", src) + } + + if src.TLSConfig == nil { + t.Fatalf("failed to set TLSConfig %#+v", src) + } + + if src.TLSConfig.InsecureSkipVerify != true { + t.Fatalf("failed to set TLSConfig %#+v", src) + } +} + +func TestNested(t *testing.T) { + type server struct { + Address []string + } + type ownserver struct { + server + OwnField string + } + + opts := []options.Option{ + options.Address("host:port"), + options.NewOption("OwnField")("fieldval"), + } + + src := &ownserver{} + + if err := options.Apply(src, opts...); err != nil { + t.Fatal(err) + } + + if src.Address[0] != "host:port" { + t.Fatalf("failed to set Address %#+v", src) + } + + if src.OwnField != "fieldval" { + t.Fatalf("failed to set OwnField %#+v", src) + } +} + +func TestAddress(t *testing.T) { + type s struct { + Address []string + } + + opts := []options.Option{options.Address("host:port")} + + src := &s{} + + if err := options.Apply(src, opts...); err != nil { + t.Fatal(err) + } + + if src.Address[0] != "host:port" { + t.Fatalf("failed to set Address %#+v", src) + } +} + +func TestNewOption(t *testing.T) { + type s struct { + Address []string + } + + opts := []options.Option{options.NewOption("Address")("host1:port1", "host2:port2")} + + src := &s{} + + if err := options.Apply(src, opts...); err != nil { + t.Fatal(err) + } + + if src.Address[0] != "host1:port1" { + t.Fatalf("failed to set Address %#+v", src) + } + if src.Address[1] != "host2:port2" { + t.Fatalf("failed to set Address %#+v", src) + } +} + +func TestArray(t *testing.T) { + type s struct { + Address [1]string + } + + opts := []options.Option{options.NewOption("Address")("host:port", "host1:port1")} + + src := &s{} + + if err := options.Apply(src, opts...); err != nil { + t.Fatal(err) + } + + if src.Address[0] != "host:port" { + t.Fatalf("failed to set Address %#+v", src) + } +} + +func TestMap(t *testing.T) { + type s struct { + Metadata map[string]string + } + + opts := []options.Option{ + options.NewOption("Metadata")("key1", "val1"), + options.NewOption("Metadata")(map[string]string{"key2": "val2"}), + } + + src := &s{} + + if err := options.Apply(src, opts...); err != nil { + t.Fatal(err) + } + + if len(src.Metadata) != 2 { + t.Fatalf("failed to set Metadata %#+v", src) + } + + if src.Metadata["key1"] != "val1" { + t.Fatalf("failed to set Metadata %#+v", src) + } + + if src.Metadata["key2"] != "val2" { + t.Fatalf("failed to set Metadata %#+v", src) + } +} diff --git a/options/util.go b/options/util.go new file mode 100644 index 00000000..92804fc3 --- /dev/null +++ b/options/util.go @@ -0,0 +1,577 @@ +package options + +import ( + "fmt" + "reflect" + + "github.com/spf13/cast" +) + +func toInt8SliceE(i interface{}) ([]int8, error) { + if i == nil { + return []int8{}, fmt.Errorf("unable to cast %#v of type %T to []int8", i, i) + } + + switch v := i.(type) { + case []int8: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]int8, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToInt8E(s.Index(j).Interface()) + if err != nil { + return []int8{}, fmt.Errorf("unable to cast %#v of type %T to []int8", i, i) + } + a[j] = val + } + return a, nil + default: + return []int8{}, fmt.Errorf("unable to cast %#v of type %T to []int8", i, i) + } +} + +func toInt16SliceE(i interface{}) ([]int16, error) { + if i == nil { + return []int16{}, fmt.Errorf("unable to cast %#v of type %T to []int16", i, i) + } + + switch v := i.(type) { + case []int16: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]int16, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToInt16E(s.Index(j).Interface()) + if err != nil { + return []int16{}, fmt.Errorf("unable to cast %#v of type %T to []int16", i, i) + } + a[j] = val + } + return a, nil + default: + return []int16{}, fmt.Errorf("unable to cast %#v of type %T to []int16", i, i) + } +} + +func toInt32SliceE(i interface{}) ([]int32, error) { + if i == nil { + return []int32{}, fmt.Errorf("unable to cast %#v of type %T to []int32", i, i) + } + + switch v := i.(type) { + case []int32: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]int32, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToInt32E(s.Index(j).Interface()) + if err != nil { + return []int32{}, fmt.Errorf("unable to cast %#v of type %T to []int32", i, i) + } + a[j] = val + } + return a, nil + default: + return []int32{}, fmt.Errorf("unable to cast %#v of type %T to []int32", i, i) + } +} + +func toInt64SliceE(i interface{}) ([]int64, error) { + if i == nil { + return []int64{}, fmt.Errorf("unable to cast %#v of type %T to []int64", i, i) + } + + switch v := i.(type) { + case []int64: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]int64, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToInt64E(s.Index(j).Interface()) + if err != nil { + return []int64{}, fmt.Errorf("unable to cast %#v of type %T to []int64", i, i) + } + a[j] = val + } + return a, nil + default: + return []int64{}, fmt.Errorf("unable to cast %#v of type %T to []int64", i, i) + } +} + +func toUintSliceE(i interface{}) ([]uint, error) { + if i == nil { + return []uint{}, fmt.Errorf("unable to cast %#v of type %T to []uint", i, i) + } + + switch v := i.(type) { + case []uint: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]uint, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToUintE(s.Index(j).Interface()) + if err != nil { + return []uint{}, fmt.Errorf("unable to cast %#v of type %T to []uint", i, i) + } + a[j] = val + } + return a, nil + default: + return []uint{}, fmt.Errorf("unable to cast %#v of type %T to []uint", i, i) + } +} + +func toUint8SliceE(i interface{}) ([]uint8, error) { + if i == nil { + return []uint8{}, fmt.Errorf("unable to cast %#v of type %T to []uint8", i, i) + } + + switch v := i.(type) { + case []uint8: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]uint8, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToUint8E(s.Index(j).Interface()) + if err != nil { + return []uint8{}, fmt.Errorf("unable to cast %#v of type %T to []uint8", i, i) + } + a[j] = val + } + return a, nil + default: + return []uint8{}, fmt.Errorf("unable to cast %#v of type %T to []uint8", i, i) + } +} + +func toUint16SliceE(i interface{}) ([]uint16, error) { + if i == nil { + return []uint16{}, fmt.Errorf("unable to cast %#v of type %T to []uint16", i, i) + } + + switch v := i.(type) { + case []uint16: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]uint16, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToUint16E(s.Index(j).Interface()) + if err != nil { + return []uint16{}, fmt.Errorf("unable to cast %#v of type %T to []uint16", i, i) + } + a[j] = val + } + return a, nil + default: + return []uint16{}, fmt.Errorf("unable to cast %#v of type %T to []uint16", i, i) + } +} + +func toUint32SliceE(i interface{}) ([]uint32, error) { + if i == nil { + return []uint32{}, fmt.Errorf("unable to cast %#v of type %T to []uint32", i, i) + } + + switch v := i.(type) { + case []uint32: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]uint32, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToUint32E(s.Index(j).Interface()) + if err != nil { + return []uint32{}, fmt.Errorf("unable to cast %#v of type %T to []uint32", i, i) + } + a[j] = val + } + return a, nil + default: + return []uint32{}, fmt.Errorf("unable to cast %#v of type %T to []uint32", i, i) + } +} + +func toUint64SliceE(i interface{}) ([]uint64, error) { + if i == nil { + return []uint64{}, fmt.Errorf("unable to cast %#v of type %T to []uint64", i, i) + } + + switch v := i.(type) { + case []uint64: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]uint64, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToUint64E(s.Index(j).Interface()) + if err != nil { + return []uint64{}, fmt.Errorf("unable to cast %#v of type %T to []uint64", i, i) + } + a[j] = val + } + return a, nil + default: + return []uint64{}, fmt.Errorf("unable to cast %#v of type %T to []uint64", i, i) + } +} + +func toFloat32SliceE(i interface{}) ([]float32, error) { + if i == nil { + return []float32{}, fmt.Errorf("unable to cast %#v of type %T to []float32", i, i) + } + + switch v := i.(type) { + case []float32: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]float32, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToFloat32E(s.Index(j).Interface()) + if err != nil { + return []float32{}, fmt.Errorf("unable to cast %#v of type %T to []float32", i, i) + } + a[j] = val + } + return a, nil + default: + return []float32{}, fmt.Errorf("unable to cast %#v of type %T to []float32", i, i) + } +} + +func toFloat64SliceE(i interface{}) ([]float64, error) { + if i == nil { + return []float64{}, fmt.Errorf("unable to cast %#v of type %T to []float64", i, i) + } + + switch v := i.(type) { + case []float64: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]float64, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := cast.ToFloat64E(s.Index(j).Interface()) + if err != nil { + return []float64{}, fmt.Errorf("unable to cast %#v of type %T to []float64", i, i) + } + a[j] = val + } + return a, nil + default: + return []float64{}, fmt.Errorf("unable to cast %#v of type %T to []float32", i, i) + } +} + +func setMap(src interface{}, dst interface{}) error { + var err error + + if src == nil { + return fmt.Errorf("unable to cast %#v of type %T", src, src) + } + if dst == nil { + return fmt.Errorf("unable to cast %#v of type %T", dst, dst) + } + + val := reflect.ValueOf(src) + + keyKind := val.Type().Key().Kind() + valKind := val.Type().Elem().Kind() + + switch v := dst.(type) { + case []interface{}: + if len(v) == 1 { + dstVal := reflect.ValueOf(v[0]) + if dstVal.Kind() != reflect.Map { + return nil + } + mapIter := dstVal.MapRange() + for mapIter.Next() { + var ( + keyVal interface{} + valVal interface{} + ) + switch keyKind { + case reflect.Bool: + keyVal, err = cast.ToBoolE(mapIter.Key()) + case reflect.String: + keyVal, err = cast.ToStringE(mapIter.Key()) + case reflect.Float32: + keyVal, err = cast.ToFloat32E(mapIter.Key()) + case reflect.Float64: + keyVal, err = cast.ToFloat64E(mapIter.Key()) + case reflect.Int8: + keyVal, err = cast.ToInt8E(mapIter.Key()) + case reflect.Int: + keyVal, err = cast.ToIntE(mapIter.Key()) + case reflect.Int16: + keyVal, err = cast.ToInt16E(mapIter.Key()) + case reflect.Int32: + keyVal, err = cast.ToInt32E(mapIter.Key()) + case reflect.Int64: + keyVal, err = cast.ToInt64E(mapIter.Key()) + case reflect.Uint8: + keyVal, err = cast.ToUint8E(mapIter.Key()) + case reflect.Uint: + keyVal, err = cast.ToUintE(mapIter.Key()) + case reflect.Uint16: + keyVal, err = cast.ToUint16E(mapIter.Key()) + case reflect.Uint32: + keyVal, err = cast.ToUint32E(mapIter.Key()) + case reflect.Uint64: + keyVal, err = cast.ToUint64E(mapIter.Key()) + } + if err != nil { + return err + } + switch valKind { + case reflect.Bool: + valVal, err = cast.ToBoolE(mapIter.Value()) + case reflect.String: + valVal, err = cast.ToStringE(mapIter.Value()) + case reflect.Float32: + valVal, err = cast.ToFloat32E(mapIter.Value()) + case reflect.Float64: + valVal, err = cast.ToFloat64E(mapIter.Value()) + case reflect.Int8: + valVal, err = cast.ToInt8E(mapIter.Value()) + case reflect.Int: + valVal, err = cast.ToIntE(mapIter.Value()) + case reflect.Int16: + valVal, err = cast.ToInt16E(mapIter.Value()) + case reflect.Int32: + valVal, err = cast.ToInt32E(mapIter.Value()) + case reflect.Int64: + valVal, err = cast.ToInt64E(mapIter.Value()) + case reflect.Uint8: + valVal, err = cast.ToUint8E(mapIter.Value()) + case reflect.Uint: + valVal, err = cast.ToUintE(mapIter.Value()) + case reflect.Uint16: + valVal, err = cast.ToUint16E(mapIter.Value()) + case reflect.Uint32: + valVal, err = cast.ToUint32E(mapIter.Value()) + case reflect.Uint64: + valVal, err = cast.ToUint64E(mapIter.Value()) + } + if err != nil { + return err + } + + val.SetMapIndex(reflect.ValueOf(keyVal), reflect.ValueOf(valVal)) + } + return nil + } + if l := len(v) % 2; l == 1 { + v = v[:len(v)-1] + } + var ( + keyVal interface{} + valVal interface{} + ) + for i := 0; i < len(v); i += 2 { + switch keyKind { + case reflect.Bool: + keyVal, err = cast.ToBoolE(v[i]) + case reflect.String: + keyVal, err = cast.ToStringE(v[i]) + case reflect.Float32: + keyVal, err = cast.ToFloat32E(v[i]) + case reflect.Float64: + keyVal, err = cast.ToFloat64E(v[i]) + case reflect.Int8: + keyVal, err = cast.ToInt8E(v[i]) + case reflect.Int: + keyVal, err = cast.ToIntE(v[i]) + case reflect.Int16: + keyVal, err = cast.ToInt16E(v[i]) + case reflect.Int32: + keyVal, err = cast.ToInt32E(v[i]) + case reflect.Int64: + keyVal, err = cast.ToInt64E(v[i]) + case reflect.Uint8: + keyVal, err = cast.ToUint8E(v[i]) + case reflect.Uint: + keyVal, err = cast.ToUintE(v[i]) + case reflect.Uint16: + keyVal, err = cast.ToUint16E(v[i]) + case reflect.Uint32: + keyVal, err = cast.ToUint32E(v[i]) + case reflect.Uint64: + keyVal, err = cast.ToUint64E(v[i]) + } + if err != nil { + return err + } + switch valKind { + case reflect.Bool: + valVal, err = cast.ToBoolE(v[i+1]) + case reflect.String: + valVal, err = cast.ToStringE(v[i+1]) + case reflect.Float32: + valVal, err = cast.ToFloat32E(v[i+1]) + case reflect.Float64: + valVal, err = cast.ToFloat64E(v[i+1]) + case reflect.Int8: + valVal, err = cast.ToInt8E(v[i+1]) + case reflect.Int: + valVal, err = cast.ToIntE(v[i+1]) + case reflect.Int16: + valVal, err = cast.ToInt16E(v[i+1]) + case reflect.Int32: + valVal, err = cast.ToInt32E(v[i+1]) + case reflect.Int64: + valVal, err = cast.ToInt64E(v[i+1]) + case reflect.Uint8: + valVal, err = cast.ToUint8E(v[i+1]) + case reflect.Uint: + valVal, err = cast.ToUintE(v[i+1]) + case reflect.Uint16: + valVal, err = cast.ToUint16E(v[i+1]) + case reflect.Uint32: + valVal, err = cast.ToUint32E(v[i+1]) + case reflect.Uint64: + valVal, err = cast.ToUint64E(v[i+1]) + } + if err != nil { + return err + } + + val.SetMapIndex(reflect.ValueOf(keyVal), reflect.ValueOf(valVal)) + } + default: + dstVal := reflect.ValueOf(dst) + if dstVal.Kind() != reflect.Map { + return nil + } + mapIter := dstVal.MapRange() + for mapIter.Next() { + var ( + keyVal interface{} + valVal interface{} + ) + switch keyKind { + case reflect.Bool: + keyVal, err = cast.ToBoolE(mapIter.Key()) + case reflect.String: + keyVal, err = cast.ToStringE(mapIter.Key()) + case reflect.Float32: + keyVal, err = cast.ToFloat32E(mapIter.Key()) + case reflect.Float64: + keyVal, err = cast.ToFloat64E(mapIter.Key()) + case reflect.Int8: + keyVal, err = cast.ToInt8E(mapIter.Key()) + case reflect.Int: + keyVal, err = cast.ToIntE(mapIter.Key()) + case reflect.Int16: + keyVal, err = cast.ToInt16E(mapIter.Key()) + case reflect.Int32: + keyVal, err = cast.ToInt32E(mapIter.Key()) + case reflect.Int64: + keyVal, err = cast.ToInt64E(mapIter.Key()) + case reflect.Uint8: + keyVal, err = cast.ToUint8E(mapIter.Key()) + case reflect.Uint: + keyVal, err = cast.ToUintE(mapIter.Key()) + case reflect.Uint16: + keyVal, err = cast.ToUint16E(mapIter.Key()) + case reflect.Uint32: + keyVal, err = cast.ToUint32E(mapIter.Key()) + case reflect.Uint64: + keyVal, err = cast.ToUint64E(mapIter.Key()) + } + if err != nil { + return err + } + switch valKind { + case reflect.Bool: + valVal, err = cast.ToBoolE(mapIter.Value()) + case reflect.String: + valVal, err = cast.ToStringE(mapIter.Value()) + case reflect.Float32: + valVal, err = cast.ToFloat32E(mapIter.Value()) + case reflect.Float64: + valVal, err = cast.ToFloat64E(mapIter.Value()) + case reflect.Int8: + valVal, err = cast.ToInt8E(mapIter.Value()) + case reflect.Int: + valVal, err = cast.ToIntE(mapIter.Value()) + case reflect.Int16: + valVal, err = cast.ToInt16E(mapIter.Value()) + case reflect.Int32: + valVal, err = cast.ToInt32E(mapIter.Value()) + case reflect.Int64: + valVal, err = cast.ToInt64E(mapIter.Value()) + case reflect.Uint8: + valVal, err = cast.ToUint8E(mapIter.Value()) + case reflect.Uint: + valVal, err = cast.ToUintE(mapIter.Value()) + case reflect.Uint16: + valVal, err = cast.ToUint16E(mapIter.Value()) + case reflect.Uint32: + valVal, err = cast.ToUint32E(mapIter.Value()) + case reflect.Uint64: + valVal, err = cast.ToUint64E(mapIter.Value()) + } + if err != nil { + return err + } + + val.SetMapIndex(reflect.ValueOf(keyVal), reflect.ValueOf(valVal)) + } + return nil + } + return nil +} -- 2.47.1 From 70db46d6bc4ea8982c29bab7a344301bfa4385b3 Mon Sep 17 00:00:00 2001 From: vtolstov Date: Tue, 14 Jan 2025 15:44:57 +0000 Subject: [PATCH 2/2] Apply Code Coverage Badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3fe5d78a..42e77793 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Micro -![Coverage](https://img.shields.io/badge/Coverage-44.8%25-yellow) +![Coverage](https://img.shields.io/badge/Coverage-43.4%25-yellow) [![License](https://img.shields.io/:license-apache-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Doc](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/go.unistack.org/micro/v3?tab=overview) [![Status](https://git.unistack.org/unistack-org/micro/actions/workflows/job_tests.yml/badge.svg?branch=v3)](https://git.unistack.org/unistack-org/micro/actions?query=workflow%3Abuild+branch%3Av3+event%3Apush) -- 2.47.1