diff --git a/README.md b/README.md
index 52d52fa..758e4bc 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,194 @@
-# form
-form to struct decoder
+Package form
+============
+
+
+[](https://godoc.org/github.com/go-playground/form)
+
+
+Package form parses url.Values and fills a struct with values, creating objects as necessary.
+
+It has the following features:
+
+- Primitives types cause zero allocations.
+- Supports map of almost all types.
+- Supports both Numbered and Normal arrays i.e. "Array[0]" and just "Array" with multiple values passed.
+- Allows for Custom Type registration.
+- Handles time.Time using RFC3339 time format by default, but can easily be changes usings registering a Custom Type.
+
+Common Questions
+
+- Does it support encoding.TextUnmarshaler? No because TextUnmarshaler only accepts []byte but posted values can have multiple values, so is not suitable.
+
+Supported Types ( out of the box )
+----------
+
+* `string`
+* `bool`
+* `int`, `int8`, `int16`, `int32`, `int64`
+* `uint`, `uint8`, `uint16`, `uint32`, `uint64`
+* `float32`, `float64`
+* `struct` and `anonymous struct`
+* `interface{}`
+* `time.Time` - by default using RFC3339
+* a `pointer` to one of the above types
+* `slice`, `array`
+* `map`
+* `custom types` can override any of the above types
+* many other types may be supported inherently (i.e. bson.ObjectId is type ObjectId string, which will get populated by the string type
+
+**NOTE**: `map`, `struct` and `slice` nesting are ad infinitum.
+
+Installation
+------------
+
+Use go get.
+
+ go get github.com/go-playground/form
+
+Then import the form package into your own code.
+
+ import "github.com/go-playground/form"
+
+Usage
+-----
+
+- Use symbol `.` for separating fields/structs. (i.e. `structfield.field`)
+- Use `[index or key]` for access to index of a slice/array or key for map. (i.e. `arrayfield[0]`, `mapfield[keyvalue]`)
+
+```html
+
+```
+
+Example
+-------
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/url"
+
+ "github.com/go-playground/form"
+)
+
+// Address contains address information
+type Address struct {
+ Name string
+ Phone string
+}
+
+// User contains user information
+type User struct {
+ Name string
+ Age uint8
+ Gender string
+ Address []Address
+ Active bool `form:"active"`
+ MapExample map[string]string
+ NestedMap map[string]map[string]string
+ NestedArray [][]string
+}
+
+// use a single instance of Decoder, it caches struct info
+var decoder *form.Decoder
+
+func main() {
+ decoder = form.NewDecoder()
+
+ // this simulates the results of http.Request's ParseForm() function
+ values := parseForm()
+
+ var user User
+
+ // must pass a pointer
+ err := decoder.Decode(&user, values)
+ if err != nil {
+ log.Panic(err)
+ }
+
+ fmt.Printf("%#v\n", user)
+}
+
+// this simulates the results of http.Request's ParseForm() function
+func parseForm() url.Values {
+ return url.Values{
+ "Name": []string{"joeybloggs"},
+ "Age": []string{"3"},
+ "Gender": []string{"Male"},
+ "Address[0].Name": []string{"26 Here Blvd."},
+ "Address[0].Phone": []string{"9(999)999-9999"},
+ "Address[1].Name": []string{"26 There Blvd."},
+ "Address[1].Phone": []string{"1(111)111-1111"},
+ "active": []string{"true"},
+ "MapExample[key]": []string{"value"},
+ "NestedMap[key][key]": []string{"value"},
+ "NestedArray[0][0]": []string{"value"},
+ }
+}
+```
+
+Registering Custom Types
+--------------
+```go
+decoder.RegisterCustomTypeFunc(func(vals []string) (interface{}, error) {
+ return time.Parse("2006-01-02", vals[0])
+ }, time.Time{})
+```
+
+Benchmarks
+------
+###### Run on MacBook Pro (Retina, 15-inch, Late 2013) 2.6 GHz Intel Core i7 16 GB 1600 MHz DDR3 using Go version go1.6.2 darwin/amd64
+
+NOTE: the 1 allocationand B/op in the first 4 is actually the struct allocating when passing it in, so primitives are actually zero allocation.
+
+```go
+go test -bench=. -benchmem=true
+
+PASS
+BenchmarkSimpleUserStruct-8 5000000 320 ns/op 64 B/op 1 allocs/op
+BenchmarkSimpleUserStructParallel-8 20000000 110 ns/op 64 B/op 1 allocs/op
+BenchmarkPrimitivesStructAllPrimitivesTypes-8 1000000 1075 ns/op 96 B/op 1 allocs/op
+BenchmarkPrimitivesStructAllPrimitivesTypesParallel-8 5000000 285 ns/op 96 B/op 1 allocs/op
+BenchmarkComplexArrayStructAllTypes-8 100000 19748 ns/op 6600 B/op 143 allocs/op
+BenchmarkComplexArrayStructAllTypesParallel-8 300000 5844 ns/op 6600 B/op 143 allocs/op
+BenchmarkComplexMapStructAllTypes-8 50000 33943 ns/op 20276 B/op 224 allocs/op
+BenchmarkComplexMapStructAllTypesParallel-8 200000 12228 ns/op 20277 B/op 224 allocs/op
+BenchmarkArrayMapNestedStruct-8 300000 4658 ns/op 1840 B/op 27 allocs/op
+BenchmarkArrayMapNestedStructParallel-8 1000000 1498 ns/op 1840 B/op 27 allocs/op
+```
+
+
+Complimentary Software
+----------------------
+
+Here is a list of software that compliments using this library post decoding.
+
+* [Validator](https://github.com/go-playground/validator) - Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving.
+* [Conform](https://github.com/leebenson/conform) - Trims, sanitizes & scrubs data based on struct tags.
+
+Package Versioning
+----------
+I'm jumping on the vendoring bandwagon, you should vendor this package as I will not
+be creating different version with gopkg.in like allot of my other libraries.
+
+Why? because my time is spread pretty thin maintaining all of the libraries I have + LIFE,
+it is so freeing not to worry about it and will help me keep pouring out bigger and better
+things for you the community.
+
+License
+------
+Distributed under MIT License, please see license file in code for more details.
\ No newline at end of file
diff --git a/doc.go b/doc.go
new file mode 100644
index 0000000..6078b8b
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,144 @@
+/*
+Package form parses url.Values and fills a struct with values, creating objects as necessary.
+
+
+It has the following features:
+
+ - Primitives types cause zero allocations.
+ - Supports map of almost all types.
+ - Supports both Numbered and Normal arrays i.e. "Array[0]" and just "Array" with multiple values passed.
+ - Allows for Custom Type registration.
+ - Handles time.Time using RFC3339 time format by default, but can easily be changes usings registering a Custom Type.
+
+Common Questions
+
+Questions
+
+ Does it support encoding.TextUnmarshaler?
+ No because TextUnmarshaler only accepts []byte but posted values can have multiple values, so is not suitable.
+
+Supported Types
+
+out of the box supported types
+
+ - string
+ - bool
+ - int, int8, int16, int32, int64
+ - uint, uint8, uint16, uint32, uint64
+ - float32, float64
+ - struct and anonymous struct
+ - interface{}
+ - time.Time` - by default using RFC3339
+ - a `pointer` to one of the above types
+ - slice, array
+ - map
+ - `custom types` can override any of the above types
+ - many other types may be supported inherently (i.e. bson.ObjectId is type ObjectId string,
+ which will get populated by the string type
+
+ **NOTE**: map, struct and slice nesting are ad infinitum.
+
+Usage
+
+symbols
+
+ - Use symbol `.` for separating fields/structs. (i.e, `structfield.field`)
+ - Use `[index or key]` for access to index of a slice/array or key for map.
+ (i.e, `arrayfield[0]`, `mapfield[keyvalue]`)
+
+html
+
+
+
+Example
+
+example parsing the above HTML
+
+ package main
+
+ import (
+ "fmt"
+ "log"
+ "net/url"
+
+ "github.com/go-playground/form"
+ )
+
+ // Address contains address information
+ type Address struct {
+ Name string
+ Phone string
+ }
+
+ // User contains user information
+ type User struct {
+ Name string
+ Age uint8
+ Gender string
+ Address []Address
+ Active bool `form:"active"`
+ MapExample map[string]string
+ NestedMap map[string]map[string]string
+ NestedArray [][]string
+ }
+
+ // use a single instance of Decoder, it caches struct info
+ var decoder *form.Decoder
+
+ func main() {
+ decoder = form.NewDecoder()
+
+ // this simulates the results of http.Request's ParseForm() function
+ values := parseForm()
+
+ var user User
+
+ // must pass a pointer
+ err := decoder.Decode(&user, values)
+ if err != nil {
+ log.Panic(err)
+ }
+
+ fmt.Printf("%#v\n", user)
+ }
+
+ // this simulates the results of http.Request's ParseForm() function
+ func parseForm() url.Values {
+ return url.Values{
+ "Name": []string{"joeybloggs"},
+ "Age": []string{"3"},
+ "Gender": []string{"Male"},
+ "Address[0].Name": []string{"26 Here Blvd."},
+ "Address[0].Phone": []string{"9(999)999-9999"},
+ "Address[1].Name": []string{"26 There Blvd."},
+ "Address[1].Phone": []string{"1(111)111-1111"},
+ "active": []string{"true"},
+ "MapExample[key]": []string{"value"},
+ "NestedMap[key][key]": []string{"value"},
+ "NestedArray[0][0]": []string{"value"},
+ }
+ }
+
+
+Registering Custom Types
+
+can easily register custom types.
+
+ decoder.RegisterCustomTypeFunc(func(vals []string) (interface{}, error) {
+ return time.Parse("2006-01-02", vals[0])
+ }, time.Time{})
+*/
+package form
diff --git a/examples/full.go b/examples/full.go
new file mode 100644
index 0000000..0e044ef
--- /dev/null
+++ b/examples/full.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/url"
+
+ "github.com/go-playground/form"
+)
+
+//
+
+// Address contains address information
+type Address struct {
+ Name string
+ Phone string
+}
+
+// User contains user information
+type User struct {
+ Name string
+ Age uint8
+ Gender string
+ Address []Address
+ Active bool `form:"active"`
+ MapExample map[string]string
+ NestedMap map[string]map[string]string
+ NestedArray [][]string
+}
+
+// use a single instance of Decoder, it caches struct info
+var decoder *form.Decoder
+
+func main() {
+ decoder = form.NewDecoder()
+
+ // this simulates the results of http.Request's ParseForm() function
+ values := parseForm()
+
+ var user User
+
+ // must pass a pointer
+ err := decoder.Decode(&user, values)
+ if err != nil {
+ log.Panic(err)
+ }
+
+ fmt.Printf("%#v\n", user)
+}
+
+// this simulates the results of http.Request's ParseForm() function
+func parseForm() url.Values {
+ return url.Values{
+ "Name": []string{"joeybloggs"},
+ "Age": []string{"3"},
+ "Gender": []string{"Male"},
+ "Address[0].Name": []string{"26 Here Blvd."},
+ "Address[0].Phone": []string{"9(999)999-9999"},
+ "Address[1].Name": []string{"26 There Blvd."},
+ "Address[1].Phone": []string{"1(111)111-1111"},
+ "active": []string{"true"},
+ "MapExample[key]": []string{"value"},
+ "NestedMap[key][key]": []string{"value"},
+ "NestedArray[0][0]": []string{"value"},
+ }
+}
diff --git a/form.go b/form.go
index 96b76d8..043608d 100644
--- a/form.go
+++ b/form.go
@@ -23,7 +23,7 @@ var (
timeType = reflect.TypeOf(time.Time{})
)
-// CustomTypeFunc ...
+// CustomTypeFunc allows for registering/overriding types to be parsed.
type CustomTypeFunc func([]string) (interface{}, error)
// DecodeErrors is a map of errors encountered during form decoding
@@ -78,14 +78,14 @@ func (d *formDecoder) setError(namespace string, err error) {
d.errs[namespace] = err
}
-// Decoder is the assembler decode instance
+// Decoder is the main decode instance
type Decoder struct {
tagName string
structCache structCacheMap
customTypeFuncs map[reflect.Type]CustomTypeFunc
}
-// NewDecoder creates a new decoder instance
+// NewDecoder creates a new decoder instance with sane defaults
func NewDecoder() *Decoder {
return &Decoder{
tagName: "form",
@@ -112,7 +112,7 @@ func (d *Decoder) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}
}
}
-// Decode decodes the given values and set the cooresponding struct values on v
+// Decode decodes the given values and sets the corresponding struct values
func (d *Decoder) Decode(v interface{}, values url.Values) (err error) {
dec := &formDecoder{
diff --git a/logo.jpg b/logo.jpg
new file mode 100644
index 0000000..2ef34f8
Binary files /dev/null and b/logo.jpg differ