♻️ Refactored form parser, added recover
This commit is contained in:
parent
df4e71f261
commit
04ce166778
|
@ -67,58 +67,71 @@ func Unmarshal(src *http.Args, dst interface{}) error {
|
||||||
|
|
||||||
// Decode reads the next form-encoded value from its input and stores it in the
|
// Decode reads the next form-encoded value from its input and stores it in the
|
||||||
// value pointed to by v.
|
// value pointed to by v.
|
||||||
func (dec *Decoder) Decode(v interface{}) error {
|
func (dec *Decoder) Decode(src interface{}) (err error) {
|
||||||
dst := reflect.ValueOf(v).Elem()
|
v := reflect.ValueOf(src).Elem()
|
||||||
if !dst.IsValid() {
|
if !v.IsValid() {
|
||||||
return errors.New("invalid input")
|
return errors.New("invalid input")
|
||||||
}
|
}
|
||||||
|
|
||||||
st := reflect.TypeOf(v).Elem()
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
if ve, ok := r.(*reflect.ValueError); ok {
|
||||||
|
err = fmt.Errorf("recovered: %w", ve)
|
||||||
|
} else {
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
for i := 0; i < dst.NumField(); i++ {
|
t := reflect.TypeOf(src).Elem()
|
||||||
field := st.Field(i)
|
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
ft := t.Field(i)
|
||||||
|
|
||||||
// NOTE(toby3d): get tag value as query name
|
// NOTE(toby3d): get tag value as query name
|
||||||
tagValue, ok := field.Tag.Lookup(tagName)
|
tagValue, ok := ft.Tag.Lookup(tagName)
|
||||||
if !ok || tagValue == "" || tagValue == "-" || !dec.source.Has(tagValue) {
|
if !ok || tagValue == "" || tagValue == "-" || !dec.source.Has(tagValue) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
field := v.Field(i)
|
||||||
|
|
||||||
// NOTE(toby3d): read struct field type
|
// NOTE(toby3d): read struct field type
|
||||||
switch field.Type.Kind() {
|
switch ft.Type.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
dst.Field(i).SetString(string(dec.source.Peek(tagValue)))
|
field.SetString(string(dec.source.Peek(tagValue)))
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
dst.Field(i).SetInt(int64(dec.source.GetUintOrZero(tagValue)))
|
field.SetInt(int64(dec.source.GetUintOrZero(tagValue)))
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
dst.Field(i).SetFloat(dec.source.GetUfloatOrZero(tagValue))
|
field.SetFloat(dec.source.GetUfloatOrZero(tagValue))
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
dst.Field(i).SetBool(dec.source.GetBool(tagValue))
|
field.SetBool(dec.source.GetBool(tagValue))
|
||||||
case reflect.Ptr: // NOTE(toby3d): pointer to another struct
|
case reflect.Ptr: // NOTE(toby3d): pointer to another struct
|
||||||
|
field.Set(reflect.New(ft.Type.Elem()))
|
||||||
|
|
||||||
// NOTE(toby3d): check what custom unmarshal method exists
|
// NOTE(toby3d): check what custom unmarshal method exists
|
||||||
beforeFunc := dst.Field(i).MethodByName("UnmarshalForm")
|
unmarshalFunc := field.MethodByName("UnmarshalForm")
|
||||||
if beforeFunc.IsNil() {
|
if unmarshalFunc.IsZero() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.Field(i).Set(reflect.New(field.Type.Elem()))
|
unmarshalFunc.Call([]reflect.Value{reflect.ValueOf(dec.source.Peek(tagValue))})
|
||||||
beforeFunc.Call([]reflect.Value{reflect.ValueOf(dec.source.Peek(tagValue))})
|
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
switch field.Type.Elem().Kind() {
|
switch ft.Type.Elem().Kind() {
|
||||||
case reflect.Uint8: // NOTE(toby3d): bytes slice
|
case reflect.Uint8: // NOTE(toby3d): bytes slice
|
||||||
dst.Field(i).SetBytes(dec.source.Peek(tagValue))
|
field.SetBytes(dec.source.Peek(tagValue))
|
||||||
case reflect.String: // NOTE(toby3d): string slice
|
case reflect.String: // NOTE(toby3d): string slice
|
||||||
values := dec.source.PeekMulti(tagValue)
|
values := dec.source.PeekMulti(tagValue)
|
||||||
slice := reflect.MakeSlice(field.Type, len(values), len(values))
|
slice := reflect.MakeSlice(ft.Type, len(values), len(values))
|
||||||
|
|
||||||
for j, v := range values {
|
for j, vv := range values {
|
||||||
slice.Index(j).SetString(string(v))
|
slice.Index(j).SetString(string(vv))
|
||||||
}
|
}
|
||||||
|
|
||||||
dst.Field(i).Set(slice)
|
field.Set(slice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue