options: generic options funcs
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
		
							
								
								
									
										222
									
								
								options/options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								options/options.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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") | ||||
| ) | ||||
							
								
								
									
										181
									
								
								options/options_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								options/options_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										577
									
								
								options/util.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										577
									
								
								options/util.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| } | ||||
		Reference in New Issue
	
	Block a user