Compare commits

..

4 Commits

Author SHA1 Message Date
b4092c6619 util/reflect: improve merge for map
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-02-05 18:27:16 +03:00
024868bfd7 api: encode body param in endpoint
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-02-02 19:35:16 +03:00
a0bbfd6d02 provide compa options
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-02-02 15:37:12 +03:00
2cb6843773 codec: fix noop codec
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-01-29 23:18:12 +03:00
4 changed files with 237 additions and 0 deletions

View File

@@ -98,6 +98,7 @@ func Encode(e *Endpoint) map[string]string {
set("method", strings.Join(e.Method, ","))
set("path", strings.Join(e.Path, ","))
set("host", strings.Join(e.Host, ","))
set("body", e.Body)
return ep
}
@@ -118,6 +119,7 @@ func Decode(e metadata.Metadata) *Endpoint {
ephost, _ := e.Get("host")
ep.Host = []string{ephost}
ep.Handler, _ = e.Get("handler")
ep.Body, _ = e.Get("body")
return ep
}

View File

@@ -114,16 +114,22 @@ func (c *noopCodec) Unmarshal(d []byte, v interface{}) error {
switch ve := v.(type) {
case string:
ve = string(d)
return nil
case *string:
*ve = string(d)
return nil
case []byte:
ve = d
return nil
case *[]byte:
*ve = d
return nil
case *Frame:
ve.Data = d
return nil
case *Message:
ve.Body = d
return nil
}
return json.Unmarshal(d, v)

View File

@@ -134,6 +134,14 @@ func BrokerServer(n string) BrokerOption {
}
}
// Client to be used for service
func Client(c ...client.Client) Option {
return func(o *Options) error {
o.Clients = c
return nil
}
}
// Clients to be used for service
func Clients(c ...client.Client) Option {
return func(o *Options) error {
@@ -161,6 +169,14 @@ func Profile(p profile.Profile) Option {
}
*/
// Server to be used for service
func Server(s ...server.Server) Option {
return func(o *Options) error {
o.Servers = s
return nil
}
}
// Servers to be used for service
func Servers(s ...server.Server) Option {
return func(o *Options) error {
@@ -169,6 +185,14 @@ func Servers(s ...server.Server) Option {
}
}
// Store sets the store to use
func Store(s ...store.Store) Option {
return func(o *Options) error {
o.Stores = s
return nil
}
}
// Stores sets the store to use
func Stores(s ...store.Store) Option {
return func(o *Options) error {
@@ -275,6 +299,14 @@ func LoggerServer(n string) LoggerOption {
}
*/
// Meter set the meter to use
func Meter(m ...meter.Meter) Option {
return func(o *Options) error {
o.Meters = m
return nil
}
}
// Meters set the meter to use
func Meters(m ...meter.Meter) Option {
return func(o *Options) error {
@@ -450,6 +482,14 @@ func Auth(a auth.Auth) Option {
}
*/
// Config sets the config for the service
func Config(c ...config.Config) Option {
return func(o *Options) error {
o.Configs = c
return nil
}
}
// Configs sets the configs for the service
func Configs(c ...config.Config) Option {
return func(o *Options) error {

View File

@@ -2,7 +2,10 @@ package reflect
import (
"errors"
"fmt"
"reflect"
"strconv"
"strings"
)
var (
@@ -119,3 +122,189 @@ func CopyFrom(a, b interface{}) {
}
}
}
func MergeMap(a interface{}, b map[string]interface{}) error {
var err error
// preprocess map
nb := make(map[string]interface{}, len(b))
for k, v := range b {
ps := strings.Split(k, ".")
if len(ps) == 1 {
nb[k] = v
continue
}
em := make(map[string]interface{})
em[ps[len(ps)-1]] = v
for i := len(ps) - 2; i > 0; i-- {
nm := make(map[string]interface{})
nm[ps[i]] = em
em = nm
}
if vm, ok := nb[ps[0]]; ok {
// nested map
nm := vm.(map[string]interface{})
for vk, vv := range em {
nm[vk] = vv
}
nb[ps[0]] = nm
} else {
nb[ps[0]] = em
}
}
ta := reflect.TypeOf(a)
if ta.Kind() == reflect.Ptr {
ta = ta.Elem()
}
va := reflect.ValueOf(a)
if va.Kind() == reflect.Ptr {
va = va.Elem()
}
for mk, mv := range nb {
vmv := reflect.ValueOf(mv)
// tmv := reflect.TypeOf(mv)
name := strings.Title(mk)
fva := va.FieldByName(name)
fta, found := ta.FieldByName(name)
if !found || !fva.IsValid() || !fva.CanSet() || fta.PkgPath != "" {
continue
}
// fast path via direct assign
if vmv.Type().AssignableTo(fta.Type) {
fva.Set(vmv)
continue
}
switch getKind(fva) {
case reflect.Bool:
err = mergeBool(fva, vmv)
case reflect.String:
err = mergeString(fva, vmv)
case reflect.Int:
err = mergeInt(fva, vmv)
case reflect.Uint:
err = mergeUint(fva, vmv)
case reflect.Float64:
err = mergeFloat(fva, vmv)
}
if err != nil {
return err
}
}
return nil
}
func mergeBool(va, vb reflect.Value) error {
switch getKind(vb) {
case reflect.Int:
if vb.Int() == 1 {
va.SetBool(true)
}
case reflect.Uint:
if vb.Uint() == 1 {
va.SetBool(true)
}
case reflect.Float64:
if vb.Float() == 1 {
va.SetBool(true)
}
case reflect.String:
if vb.String() == "1" || vb.String() == "true" {
vb.SetBool(true)
}
default:
return fmt.Errorf("cant merge %v %s with %v %s", va, va.Kind(), vb, vb.Kind())
}
return nil
}
func mergeString(va, vb reflect.Value) error {
switch getKind(vb) {
case reflect.Int:
va.SetString(fmt.Sprintf("%d", vb.Int()))
case reflect.Uint:
va.SetString(fmt.Sprintf("%d", vb.Uint()))
case reflect.Float64:
va.SetString(fmt.Sprintf("%f", vb.Float()))
case reflect.String:
va.Set(vb)
default:
return fmt.Errorf("cant merge %v %s with %v %s", va, va.Kind(), vb, vb.Kind())
}
return nil
}
func mergeInt(va, vb reflect.Value) error {
switch getKind(vb) {
case reflect.Int:
va.Set(vb)
case reflect.Uint:
va.SetInt(int64(vb.Uint()))
case reflect.Float64:
va.SetInt(int64(vb.Float()))
case reflect.String:
if f, err := strconv.ParseInt(vb.String(), 10, va.Type().Bits()); err != nil {
return err
} else {
va.SetInt(f)
}
default:
return fmt.Errorf("cant merge %v %s with %v %s", va, va.Kind(), vb, vb.Kind())
}
return nil
}
func mergeUint(va, vb reflect.Value) error {
switch getKind(vb) {
case reflect.Int:
va.SetUint(uint64(vb.Int()))
case reflect.Uint:
va.Set(vb)
case reflect.Float64:
va.SetUint(uint64(vb.Float()))
case reflect.String:
if f, err := strconv.ParseUint(vb.String(), 10, va.Type().Bits()); err != nil {
return err
} else {
va.SetUint(f)
}
default:
return fmt.Errorf("cant merge %v %s with %v %s", va, va.Kind(), vb, vb.Kind())
}
return nil
}
func mergeFloat(va, vb reflect.Value) error {
switch getKind(vb) {
case reflect.Int:
va.SetFloat(float64(vb.Int()))
case reflect.Uint:
va.SetFloat(float64(vb.Uint()))
case reflect.Float64:
va.Set(vb)
case reflect.String:
if f, err := strconv.ParseFloat(vb.String(), va.Type().Bits()); err != nil {
return err
} else {
va.SetFloat(f)
}
default:
return fmt.Errorf("cant merge %v %s with %v %s", va, va.Kind(), vb, vb.Kind())
}
return nil
}
func getKind(val reflect.Value) reflect.Kind {
kind := val.Kind()
switch {
case kind >= reflect.Int && kind <= reflect.Int64:
return reflect.Int
case kind >= reflect.Uint && kind <= reflect.Uint64:
return reflect.Uint
case kind >= reflect.Float32 && kind <= reflect.Float64:
return reflect.Float64
}
return kind
}