chore: better structure decoder
This commit is contained in:
parent
afb2364ca2
commit
8a2d1ec5a7
1 changed files with 78 additions and 13 deletions
|
@ -86,11 +86,16 @@ func (d *Decoder) Decode(src map[string]any, dst any) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Decoder) decode(name string, data any, val reflect.Value) error {
|
func (d *Decoder) decode(name string, data any, val reflect.Value) error {
|
||||||
switch val.Kind() {
|
kind := val.Kind()
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
switch {
|
||||||
|
case isInt(kind):
|
||||||
return d.decodeInt(name, data, val)
|
return d.decodeInt(name, data, val)
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
case isUint(kind):
|
||||||
return d.decodeUint(name, data, val)
|
return d.decodeUint(name, data, val)
|
||||||
|
case isFloat(kind):
|
||||||
|
return d.decodeFloat(name, data, val)
|
||||||
|
}
|
||||||
|
switch kind {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return d.decodeString(name, data, val)
|
return d.decodeString(name, data, val)
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
|
@ -108,15 +113,42 @@ func (d *Decoder) decode(name string, data any, val reflect.Value) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isInt(kind reflect.Kind) bool {
|
||||||
|
switch kind {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isUint(kind reflect.Kind) bool {
|
||||||
|
switch kind {
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFloat(kind reflect.Kind) bool {
|
||||||
|
switch kind {
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeInt(name string, data any, val reflect.Value) (err error) {
|
func (d *Decoder) decodeInt(name string, data any, val reflect.Value) (err error) {
|
||||||
dataVal := reflect.ValueOf(data)
|
dataVal := reflect.ValueOf(data)
|
||||||
kind := dataVal.Kind()
|
kind := dataVal.Kind()
|
||||||
switch {
|
switch {
|
||||||
case kind == reflect.Int || kind == reflect.Int8 || kind == reflect.Int16 || kind == reflect.Int32 || kind == reflect.Int64:
|
case isInt(kind):
|
||||||
val.SetInt(dataVal.Int())
|
val.SetInt(dataVal.Int())
|
||||||
case (kind == reflect.Uint || kind == reflect.Uint8 || kind == reflect.Uint16 || kind == reflect.Uint32 || kind == reflect.Uint64) && d.option.WeaklyTypedInput:
|
case isUint(kind) && d.option.WeaklyTypedInput:
|
||||||
val.SetInt(int64(dataVal.Uint()))
|
val.SetInt(int64(dataVal.Uint()))
|
||||||
case kind == reflect.Float64 && d.option.WeaklyTypedInput:
|
case isFloat(kind) && d.option.WeaklyTypedInput:
|
||||||
val.SetInt(int64(dataVal.Float()))
|
val.SetInt(int64(dataVal.Float()))
|
||||||
case kind == reflect.String && d.option.WeaklyTypedInput:
|
case kind == reflect.String && d.option.WeaklyTypedInput:
|
||||||
var i int64
|
var i int64
|
||||||
|
@ -139,12 +171,12 @@ func (d *Decoder) decodeUint(name string, data any, val reflect.Value) (err erro
|
||||||
dataVal := reflect.ValueOf(data)
|
dataVal := reflect.ValueOf(data)
|
||||||
kind := dataVal.Kind()
|
kind := dataVal.Kind()
|
||||||
switch {
|
switch {
|
||||||
case kind == reflect.Uint || kind == reflect.Uint8 || kind == reflect.Uint16 || kind == reflect.Uint32 || kind == reflect.Uint64:
|
case isUint(kind):
|
||||||
val.SetUint(dataVal.Uint())
|
val.SetUint(dataVal.Uint())
|
||||||
case (kind == reflect.Int || kind == reflect.Int8 || kind == reflect.Int16 || kind == reflect.Int32 || kind == reflect.Int64) && d.option.WeaklyTypedInput:
|
case isInt(kind) && d.option.WeaklyTypedInput:
|
||||||
val.SetUint(uint64(dataVal.Int()))
|
val.SetUint(uint64(dataVal.Int()))
|
||||||
case kind == reflect.Float64 && d.option.WeaklyTypedInput:
|
case isFloat(kind) && d.option.WeaklyTypedInput:
|
||||||
val.SetUint(uint64(int64(dataVal.Float())))
|
val.SetUint(uint64(dataVal.Float()))
|
||||||
case kind == reflect.String && d.option.WeaklyTypedInput:
|
case kind == reflect.String && d.option.WeaklyTypedInput:
|
||||||
var i uint64
|
var i uint64
|
||||||
i, err = strconv.ParseUint(dataVal.String(), 0, val.Type().Bits())
|
i, err = strconv.ParseUint(dataVal.String(), 0, val.Type().Bits())
|
||||||
|
@ -162,14 +194,45 @@ func (d *Decoder) decodeUint(name string, data any, val reflect.Value) (err erro
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) (err error) {
|
||||||
|
dataVal := reflect.ValueOf(data)
|
||||||
|
kind := dataVal.Kind()
|
||||||
|
switch {
|
||||||
|
case isFloat(kind):
|
||||||
|
val.SetFloat(dataVal.Float())
|
||||||
|
case isUint(kind):
|
||||||
|
val.SetFloat(float64(dataVal.Uint()))
|
||||||
|
case isInt(kind) && d.option.WeaklyTypedInput:
|
||||||
|
val.SetFloat(float64(dataVal.Int()))
|
||||||
|
case kind == reflect.String && d.option.WeaklyTypedInput:
|
||||||
|
var i float64
|
||||||
|
i, err = strconv.ParseFloat(dataVal.String(), val.Type().Bits())
|
||||||
|
if err == nil {
|
||||||
|
val.SetFloat(i)
|
||||||
|
} else {
|
||||||
|
err = fmt.Errorf("cannot parse '%s' as int: %s", name, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"'%s' expected type '%s', got unconvertible type '%s'",
|
||||||
|
name, val.Type(), dataVal.Type(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Decoder) decodeString(name string, data any, val reflect.Value) (err error) {
|
func (d *Decoder) decodeString(name string, data any, val reflect.Value) (err error) {
|
||||||
dataVal := reflect.ValueOf(data)
|
dataVal := reflect.ValueOf(data)
|
||||||
kind := dataVal.Kind()
|
kind := dataVal.Kind()
|
||||||
switch {
|
switch {
|
||||||
case kind == reflect.String:
|
case kind == reflect.String:
|
||||||
val.SetString(dataVal.String())
|
val.SetString(dataVal.String())
|
||||||
case kind == reflect.Int && d.option.WeaklyTypedInput:
|
case isInt(kind) && d.option.WeaklyTypedInput:
|
||||||
val.SetString(strconv.FormatInt(dataVal.Int(), 10))
|
val.SetString(strconv.FormatInt(dataVal.Int(), 10))
|
||||||
|
case isUint(kind) && d.option.WeaklyTypedInput:
|
||||||
|
val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
|
||||||
|
case isFloat(kind) && d.option.WeaklyTypedInput:
|
||||||
|
val.SetString(strconv.FormatFloat(dataVal.Float(), 'E', -1, dataVal.Type().Bits()))
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf(
|
err = fmt.Errorf(
|
||||||
"'%s' expected type '%s', got unconvertible type '%s'",
|
"'%s' expected type '%s', got unconvertible type '%s'",
|
||||||
|
@ -185,8 +248,10 @@ func (d *Decoder) decodeBool(name string, data any, val reflect.Value) (err erro
|
||||||
switch {
|
switch {
|
||||||
case kind == reflect.Bool:
|
case kind == reflect.Bool:
|
||||||
val.SetBool(dataVal.Bool())
|
val.SetBool(dataVal.Bool())
|
||||||
case kind == reflect.Int && d.option.WeaklyTypedInput:
|
case isInt(kind) && d.option.WeaklyTypedInput:
|
||||||
val.SetBool(dataVal.Int() != 0)
|
val.SetBool(dataVal.Int() != 0)
|
||||||
|
case isUint(kind) && d.option.WeaklyTypedInput:
|
||||||
|
val.SetString(strconv.FormatUint(dataVal.Uint(), 10))
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf(
|
err = fmt.Errorf(
|
||||||
"'%s' expected type '%s', got unconvertible type '%s'",
|
"'%s' expected type '%s', got unconvertible type '%s'",
|
||||||
|
@ -201,7 +266,7 @@ func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error {
|
||||||
valType := val.Type()
|
valType := val.Type()
|
||||||
valElemType := valType.Elem()
|
valElemType := valType.Elem()
|
||||||
|
|
||||||
if dataVal.Kind() == reflect.String && valElemType.Kind() == reflect.Uint8 {
|
if dataVal.Kind() == reflect.String && valElemType.Kind() == reflect.Uint8 { // from encoding/json
|
||||||
s := []byte(dataVal.String())
|
s := []byte(dataVal.String())
|
||||||
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
|
||||||
n, err := base64.StdEncoding.Decode(b, s)
|
n, err := base64.StdEncoding.Decode(b, s)
|
||||||
|
|
Loading…
Reference in a new issue