95 lines
2.1 KiB
Go
95 lines
2.1 KiB
Go
package router
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
type genericValues map[string][]string
|
|
|
|
func (gv genericValues) Marshal(data any, tag string) (err error) {
|
|
if gv == nil {
|
|
gv = make(genericValues)
|
|
}
|
|
d := reflect.ValueOf(data)
|
|
if d.Kind() == reflect.Pointer || d.Kind() == reflect.Interface {
|
|
d = d.Elem()
|
|
}
|
|
if d.Kind() != reflect.Struct {
|
|
err = fmt.Errorf("expected struct input for data")
|
|
return
|
|
}
|
|
for i := 0; i < d.NumField(); i++ {
|
|
key, ok := d.Type().Field(i).Tag.Lookup(tag)
|
|
if !ok || key == "" {
|
|
continue
|
|
}
|
|
v := make([]string, 0)
|
|
val := d.Field(i)
|
|
if val.Kind() == reflect.Pointer || val.Kind() == reflect.Interface {
|
|
val = val.Elem()
|
|
}
|
|
if val.Kind() == reflect.Slice || val.Kind() == reflect.Array {
|
|
for j := 0; j < val.Len(); j++ {
|
|
item := val.Index(j)
|
|
if item.Kind() == reflect.Pointer || item.Kind() == reflect.Interface {
|
|
item = item.Elem()
|
|
}
|
|
v = append(v, fmt.Sprintf("%s", item.Interface()))
|
|
}
|
|
} else {
|
|
v = append(v, fmt.Sprintf("%s", val.Interface()))
|
|
}
|
|
gv[key] = v
|
|
}
|
|
return
|
|
}
|
|
|
|
func (gv genericValues) Unmarshal(data any, tag string) (err error) {
|
|
if gv == nil {
|
|
err = fmt.Errorf("expected map to exist")
|
|
return
|
|
}
|
|
d := reflect.ValueOf(data)
|
|
if d.Kind() != reflect.Pointer || d.Kind() != reflect.Interface {
|
|
err = fmt.Errorf("expected pointer for data")
|
|
return
|
|
}
|
|
d = d.Elem()
|
|
if d.Kind() != reflect.Struct {
|
|
err = fmt.Errorf("expected struct input for data")
|
|
return
|
|
}
|
|
for key, value := range gv {
|
|
var v reflect.Value
|
|
if len(value) == 1 {
|
|
v = reflect.ValueOf(value[0])
|
|
} else {
|
|
v = reflect.ValueOf(value)
|
|
}
|
|
for i := 0; i < d.NumField(); i++ {
|
|
k, ok := d.Type().Field(i).Tag.Lookup(tag)
|
|
if !ok || k != key {
|
|
continue
|
|
}
|
|
val := d.Field(i)
|
|
if val.Kind() == reflect.Pointer || val.Kind() == reflect.Interface {
|
|
val = val.Elem()
|
|
}
|
|
if !val.CanSet() {
|
|
err = fmt.Errorf("could not set value for %s", d.Type().Field(i).Name)
|
|
}
|
|
switch val.Kind() {
|
|
case reflect.String:
|
|
val.Set(reflect.ValueOf(strings.Join(value, "; ")))
|
|
default:
|
|
if v.CanConvert(val.Type()) {
|
|
val.Set(v.Convert(val.Type()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|