Skip to content

Commit

Permalink
Merge pull request #36 from monoculum/better-docs
Browse files Browse the repository at this point in the history
better docs
  • Loading branch information
emilgpa authored Sep 23, 2020
2 parents b041775 + ddb8ac2 commit bd383fd
Showing 1 changed file with 47 additions and 48 deletions.
95 changes: 47 additions & 48 deletions formam.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@ const (

// pathMap holds the values of a map with its key and values correspondent
type pathMap struct {
ma reflect.Value
key string
value reflect.Value

path string
field reflect.Value // map
key string // key of map
value reflect.Value // value of map
path string // form's path associated to map
}

// pathMaps holds the values for each key
Expand All @@ -32,7 +31,7 @@ type pathMaps []*pathMap
// find finds and gets the value by the given key
func (m pathMaps) find(id reflect.Value, key string) *pathMap {
for i := range m {
if m[i].ma == id && m[i].key == key {
if m[i].field == id && m[i].key == key {
return m[i]
}
}
Expand All @@ -44,33 +43,33 @@ type DecodeCustomTypeFunc func([]string) (interface{}, error)

// decodeCustomTypeField is registered for a specific field.
type decodeCustomTypeField struct {
fn DecodeCustomTypeFunc
field reflect.Value
fun DecodeCustomTypeFunc
}

// decodeCustomType fields for custom types.
type decodeCustomType struct {
fun DecodeCustomTypeFunc
fn DecodeCustomTypeFunc
fields []*decodeCustomTypeField
}

// Decoder to decode a form.
type Decoder struct {
main reflect.Value
formValues url.Values
opts *DecoderOptions
main reflect.Value // reflect value of main struct/slice to decode
values url.Values // all values of form
opts *DecoderOptions // options

curr reflect.Value
values []string
curr reflect.Value // current field (as reflect value)
currValues []string // values of current path to decode

path string
field string
index string
path string // current path
field string // current field (as string)
index string // current index/key of a field: slice/array/map
//isKey bool

maps pathMaps
maps pathMaps // maps cached (it's decoded to the end)

customTypes map[reflect.Type]*decodeCustomType
customTypes map[reflect.Type]*decodeCustomType // custom types registered
}

// DecoderOptions options for decoding the values.
Expand Down Expand Up @@ -105,12 +104,12 @@ func (dec *Decoder) RegisterCustomType(fn DecodeCustomTypeFunc, types []interfac
for i := range types {
typ := reflect.TypeOf(types[i])
if dec.customTypes[typ] == nil {
dec.customTypes[typ] = &decodeCustomType{fun: fn, fields: make([]*decodeCustomTypeField, 0, lenFields)}
dec.customTypes[typ] = &decodeCustomType{fn: fn, fields: make([]*decodeCustomTypeField, 0, lenFields)}
}
if lenFields > 0 {
for j := range fields {
val := reflect.ValueOf(fields[j])
field := &decodeCustomTypeField{field: val, fun: fn}
field := &decodeCustomTypeField{field: val, fn: fn}
dec.customTypes[typ].fields = append(dec.customTypes[typ].fields, field)
}
}
Expand Down Expand Up @@ -141,7 +140,7 @@ func (dec Decoder) Decode(vs url.Values, dst interface{}) error {
return newError(ErrCodeNotAPointer, "", "", "dst %q is not a pointer", main.Kind())
}
dec.main = main.Elem()
dec.formValues = vs
dec.values = vs
return dec.init()
}

Expand All @@ -153,8 +152,8 @@ func Decode(vs url.Values, dst interface{}) error {
return newError(ErrCodeNotAPointer, "", "", "dst %q is not a pointer", main.Kind())
}
dec := &Decoder{
main: main.Elem(),
formValues: vs,
main: main.Elem(),
values: vs,
opts: &DecoderOptions{
TagName: tagName,
MaxSize: maxSize,
Expand All @@ -166,9 +165,9 @@ func Decode(vs url.Values, dst interface{}) error {
// init initializes the decoding
func (dec Decoder) init() error {
// iterate over the form's values and decode it
for k, v := range dec.formValues {
for k, v := range dec.values {
dec.path = k
dec.values = v
dec.currValues = v
dec.curr = dec.main
if err := dec.analyzePath(); err != nil {
if dec.curr.Kind() == reflect.Struct && dec.opts.IgnoreUnknownKeys {
Expand All @@ -179,7 +178,7 @@ func (dec Decoder) init() error {
}
// set values of maps
for _, v := range dec.maps {
key := v.ma.Type().Key()
key := v.field.Type().Key()
ptr := false
// check if the key implements the UnmarshalText interface
var val reflect.Value
Expand All @@ -192,7 +191,7 @@ func (dec Decoder) init() error {
// decode key
dec.path = v.path
dec.field = v.path
dec.values = []string{v.key}
dec.currValues = []string{v.key}
dec.curr = val
//dec.isKey = true
if err := dec.decode(); err != nil {
Expand All @@ -203,7 +202,7 @@ func (dec Decoder) init() error {
dec.curr = dec.curr.Addr()
}
// set key with its value
v.ma.SetMapIndex(dec.curr, v.value)
v.field.SetMapIndex(dec.curr, v.value)
}
return nil
}
Expand Down Expand Up @@ -347,13 +346,13 @@ func (dec *Decoder) traverseInMap(byField bool) {
if dec.maps == nil {
dec.maps = make(pathMaps, 0, 500)
}
m := reflect.New(n.Elem()).Elem()
val := reflect.New(n.Elem()).Elem()
if byField {
dec.maps = append(dec.maps, &pathMap{dec.curr, dec.field, m, dec.path})
dec.maps = append(dec.maps, &pathMap{dec.curr, dec.field, val, dec.path})
} else {
dec.maps = append(dec.maps, &pathMap{dec.curr, dec.index, m, dec.path})
dec.maps = append(dec.maps, &pathMap{dec.curr, dec.index, val, dec.path})
}
dec.curr = m
dec.curr = val
}
if dec.curr.IsNil() {
// map is nil
Expand Down Expand Up @@ -422,7 +421,7 @@ func (dec *Decoder) decode() error {
if dec.index == "" {
// not has index, so to decode all values in the slice
// only for slices
err := dec.expandSlice(len(dec.values))
err := dec.expandSlice(len(dec.currValues))
if err != nil {
return newError(ErrCodeArraySize, dec.field, dec.path, "%s", err)
}
Expand All @@ -446,9 +445,9 @@ func (dec *Decoder) decode() error {
return dec.decode()
}
case reflect.String:
dec.curr.SetString(dec.values[0])
dec.curr.SetString(dec.currValues[0])
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if num, err := strconv.ParseInt(dec.values[0], 10, dec.curr.Type().Bits()); err != nil {
if num, err := strconv.ParseInt(dec.currValues[0], 10, dec.curr.Type().Bits()); err != nil {
code := ErrCodeConversion
if err, ok := err.(*strconv.NumError); ok && err.Err == strconv.ErrRange {
code = ErrCodeRange
Expand All @@ -458,7 +457,7 @@ func (dec *Decoder) decode() error {
dec.curr.SetInt(num)
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
if num, err := strconv.ParseUint(dec.values[0], 10, dec.curr.Type().Bits()); err != nil {
if num, err := strconv.ParseUint(dec.currValues[0], 10, dec.curr.Type().Bits()); err != nil {
code := ErrCodeConversion
if err, ok := err.(*strconv.NumError); ok && err.Err == strconv.ErrRange {
code = ErrCodeRange
Expand All @@ -468,7 +467,7 @@ func (dec *Decoder) decode() error {
dec.curr.SetUint(num)
}
case reflect.Float32, reflect.Float64:
if num, err := strconv.ParseFloat(dec.values[0], dec.curr.Type().Bits()); err != nil {
if num, err := strconv.ParseFloat(dec.currValues[0], dec.curr.Type().Bits()); err != nil {
code := ErrCodeConversion
if err, ok := err.(*strconv.NumError); ok && err.Err == strconv.ErrRange {
code = ErrCodeRange
Expand All @@ -478,15 +477,15 @@ func (dec *Decoder) decode() error {
dec.curr.SetFloat(num)
}
case reflect.Bool:
switch dec.values[0] {
switch dec.currValues[0] {
case "true", "on", "1", "checked":
dec.curr.SetBool(true)
default:
dec.curr.SetBool(false)
return nil
}
case reflect.Interface:
dec.curr.Set(reflect.ValueOf(dec.values[0]))
dec.curr.Set(reflect.ValueOf(dec.currValues[0]))
case reflect.Ptr:
n := reflect.New(dec.curr.Type().Elem())
if dec.curr.CanSet() {
Expand All @@ -501,16 +500,16 @@ func (dec *Decoder) decode() error {
case time.Time:
var t time.Time
// if the value is empty then no to try to parse it and leave "t" as a zero value to set it in the field
if dec.values[0] != "" {
if dec.currValues[0] != "" {
var err error
t, err = time.Parse("2006-01-02", dec.values[0])
t, err = time.Parse("2006-01-02", dec.currValues[0])
if err != nil {
return newError(ErrCodeConversion, dec.field, dec.path, "could not parse field: %s", err)
}
}
dec.curr.Set(reflect.ValueOf(t))
case url.URL:
u, err := url.Parse(dec.values[0])
u, err := url.Parse(dec.currValues[0])
if err != nil {
return newError(ErrCodeConversion, dec.field, dec.path, "could not parse field: %s", err)
}
Expand Down Expand Up @@ -618,9 +617,9 @@ func (dec *Decoder) expandSlice(length int) error {
// setValues set the values in current slice/array
func (dec *Decoder) setValues() error {
tmp := dec.curr // hold current field
for i, v := range dec.values {
for i, v := range dec.currValues {
dec.curr = tmp.Index(i)
dec.values[0] = v
dec.currValues[0] = v
if err := dec.decode(); err != nil {
return err
}
Expand All @@ -639,7 +638,7 @@ func (dec *Decoder) isCustomType() (bool, error) {
// check if the current field is registered
// in the fields of the custom type
if v.fields[i].field.Elem() == dec.curr {
va, err := v.fields[i].fun(dec.values)
va, err := v.fields[i].fn(dec.currValues)
if err != nil {
return true, err
}
Expand All @@ -649,8 +648,8 @@ func (dec *Decoder) isCustomType() (bool, error) {
}
}
// check if the default function exists for fields not specific
if v.fun != nil {
va, err := v.fun(dec.values)
if v.fn != nil {
va, err := v.fn(dec.currValues)
if err != nil {
return true, err
}
Expand Down Expand Up @@ -685,7 +684,7 @@ func (dec *Decoder) isUnmarshalText(v reflect.Value) (bool, error) {
return false, nil
}
// return result
return true, m.UnmarshalText([]byte(dec.values[0]))
return true, m.UnmarshalText([]byte(dec.currValues[0]))
}

// getTagName get tag by the name passed by argument
Expand Down

0 comments on commit bd383fd

Please sign in to comment.