Этот коммит содержится в:
Christopher Speller
2018-02-16 06:47:51 -08:00
коммит произвёл Joram Wilander
родитель b112747de7
Коммит 6d8f122a51
602 изменённых файлов: 23090 добавлений и 129178 удалений

18
vendor/github.com/gorilla/schema/.travis.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,18 @@
language: go
sudo: false
matrix:
include:
- go: 1.5
- go: 1.6
- go: 1.7
- go: 1.8
- go: tip
allow_failures:
- go: tip
script:
- go get -t -v ./...
- diff -u <(echo -n) <(gofmt -d .)
- go vet $(go list ./... | grep -v /vendor/)
- go test -v -race ./...

27
vendor/github.com/gorilla/schema/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,27 @@
Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

90
vendor/github.com/gorilla/schema/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,90 @@
schema
======
[![GoDoc](https://godoc.org/github.com/gorilla/schema?status.svg)](https://godoc.org/github.com/gorilla/schema) [![Build Status](https://travis-ci.org/gorilla/schema.png?branch=master)](https://travis-ci.org/gorilla/schema)
[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/schema/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/schema?badge)
Package gorilla/schema converts structs to and from form values.
## Example
Here's a quick example: we parse POST form values and then decode them into a struct:
```go
// Set a Decoder instance as a package global, because it caches
// meta-data about structs, and an instance can be shared safely.
var decoder = schema.NewDecoder()
type Person struct {
Name string
Phone string
}
func MyHandler(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
// Handle error
}
var person Person
// r.PostForm is a map of our POST form values
err := decoder.Decode(&person, r.PostForm)
if err != nil {
// Handle error
}
// Do something with person.Name or person.Phone
}
```
Conversely, contents of a struct can be encoded into form values. Here's a variant of the previous example using the Encoder:
```go
var encoder = schema.NewEncoder()
func MyHttpRequest() {
person := Person{"Jane Doe", "555-5555"}
form := url.Values{}
err := encoder.Encode(person, form)
if err != nil {
// Handle error
}
// Use form values, for example, with an http client
client := new(http.Client)
res, err := client.PostForm("http://my-api.test", form)
}
```
To define custom names for fields, use a struct tag "schema". To not populate certain fields, use a dash for the name and it will be ignored:
```go
type Person struct {
Name string `schema:"name"` // custom name
Phone string `schema:"phone"` // custom name
Admin bool `schema:"-"` // this field is never set
}
```
The supported field types in the struct are:
* bool
* float variants (float32, float64)
* int variants (int, int8, int16, int32, int64)
* string
* uint variants (uint, uint8, uint16, uint32, uint64)
* struct
* a pointer to one of the above types
* a slice or a pointer to a slice of one of the above types
Unsupported types are simply ignored, however custom types can be registered to be converted.
More examples are available on the Gorilla website: http://www.gorillatoolkit.org/pkg/schema
## License
BSD licensed. See the LICENSE file for details.

264
vendor/github.com/gorilla/schema/cache.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,264 @@
// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package schema
import (
"errors"
"reflect"
"strconv"
"strings"
"sync"
)
var invalidPath = errors.New("schema: invalid path")
// newCache returns a new cache.
func newCache() *cache {
c := cache{
m: make(map[reflect.Type]*structInfo),
regconv: make(map[reflect.Type]Converter),
tag: "schema",
}
return &c
}
// cache caches meta-data about a struct.
type cache struct {
l sync.RWMutex
m map[reflect.Type]*structInfo
regconv map[reflect.Type]Converter
tag string
}
// registerConverter registers a converter function for a custom type.
func (c *cache) registerConverter(value interface{}, converterFunc Converter) {
c.regconv[reflect.TypeOf(value)] = converterFunc
}
// parsePath parses a path in dotted notation verifying that it is a valid
// path to a struct field.
//
// It returns "path parts" which contain indices to fields to be used by
// reflect.Value.FieldByString(). Multiple parts are required for slices of
// structs.
func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) {
var struc *structInfo
var field *fieldInfo
var index64 int64
var err error
parts := make([]pathPart, 0)
path := make([]string, 0)
keys := strings.Split(p, ".")
for i := 0; i < len(keys); i++ {
if t.Kind() != reflect.Struct {
return nil, invalidPath
}
if struc = c.get(t); struc == nil {
return nil, invalidPath
}
if field = struc.get(keys[i]); field == nil {
return nil, invalidPath
}
// Valid field. Append index.
path = append(path, field.name)
if field.ss {
// Parse a special case: slices of structs.
// i+1 must be the slice index.
//
// Now that struct can implements TextUnmarshaler interface,
// we don't need to force the struct's fields to appear in the path.
// So checking i+2 is not necessary anymore.
i++
if i+1 > len(keys) {
return nil, invalidPath
}
if index64, err = strconv.ParseInt(keys[i], 10, 0); err != nil {
return nil, invalidPath
}
parts = append(parts, pathPart{
path: path,
field: field,
index: int(index64),
})
path = make([]string, 0)
// Get the next struct type, dropping ptrs.
if field.typ.Kind() == reflect.Ptr {
t = field.typ.Elem()
} else {
t = field.typ
}
if t.Kind() == reflect.Slice {
t = t.Elem()
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
}
} else if field.typ.Kind() == reflect.Ptr {
t = field.typ.Elem()
} else {
t = field.typ
}
}
// Add the remaining.
parts = append(parts, pathPart{
path: path,
field: field,
index: -1,
})
return parts, nil
}
// get returns a cached structInfo, creating it if necessary.
func (c *cache) get(t reflect.Type) *structInfo {
c.l.RLock()
info := c.m[t]
c.l.RUnlock()
if info == nil {
info = c.create(t, nil)
c.l.Lock()
c.m[t] = info
c.l.Unlock()
}
return info
}
// create creates a structInfo with meta-data about a struct.
func (c *cache) create(t reflect.Type, info *structInfo) *structInfo {
if info == nil {
info = &structInfo{fields: []*fieldInfo{}}
}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.Anonymous {
ft := field.Type
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
}
if ft.Kind() == reflect.Struct {
bef := len(info.fields)
c.create(ft, info)
for _, fi := range info.fields[bef:len(info.fields)] {
// exclude required check because duplicated to embedded field
fi.required = false
}
}
}
c.createField(field, info)
}
return info
}
// createField creates a fieldInfo for the given field.
func (c *cache) createField(field reflect.StructField, info *structInfo) {
alias, options := fieldAlias(field, c.tag)
if alias == "-" {
// Ignore this field.
return
}
// Check if the type is supported and don't cache it if not.
// First let's get the basic type.
isSlice, isStruct := false, false
ft := field.Type
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
}
if isSlice = ft.Kind() == reflect.Slice; isSlice {
ft = ft.Elem()
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
}
}
if ft.Kind() == reflect.Array {
ft = ft.Elem()
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
}
}
if isStruct = ft.Kind() == reflect.Struct; !isStruct {
if c.converter(ft) == nil && builtinConverters[ft.Kind()] == nil {
// Type is not supported.
return
}
}
info.fields = append(info.fields, &fieldInfo{
typ: field.Type,
name: field.Name,
ss: isSlice && isStruct,
alias: alias,
anon: field.Anonymous,
required: options.Contains("required"),
})
}
// converter returns the converter for a type.
func (c *cache) converter(t reflect.Type) Converter {
return c.regconv[t]
}
// ----------------------------------------------------------------------------
type structInfo struct {
fields []*fieldInfo
}
func (i *structInfo) get(alias string) *fieldInfo {
for _, field := range i.fields {
if strings.EqualFold(field.alias, alias) {
return field
}
}
return nil
}
type fieldInfo struct {
typ reflect.Type
name string // field name in the struct.
ss bool // true if this is a slice of structs.
alias string
anon bool // is an embedded field
required bool // tag option
}
type pathPart struct {
field *fieldInfo
path []string // path to the field: walks structs using field names.
index int // struct index in slices of structs.
}
// ----------------------------------------------------------------------------
// fieldAlias parses a field tag to get a field alias.
func fieldAlias(field reflect.StructField, tagName string) (alias string, options tagOptions) {
if tag := field.Tag.Get(tagName); tag != "" {
alias, options = parseTag(tag)
}
if alias == "" {
alias = field.Name
}
return alias, options
}
// tagOptions is the string following a comma in a struct field's tag, or
// the empty string. It does not include the leading comma.
type tagOptions []string
// parseTag splits a struct field's url tag into its name and comma-separated
// options.
func parseTag(tag string) (string, tagOptions) {
s := strings.Split(tag, ",")
return s[0], s[1:]
}
// Contains checks whether the tagOptions contains the specified option.
func (o tagOptions) Contains(option string) bool {
for _, s := range o {
if s == option {
return true
}
}
return false
}

145
vendor/github.com/gorilla/schema/converter.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,145 @@
// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package schema
import (
"reflect"
"strconv"
)
type Converter func(string) reflect.Value
var (
invalidValue = reflect.Value{}
boolType = reflect.Bool
float32Type = reflect.Float32
float64Type = reflect.Float64
intType = reflect.Int
int8Type = reflect.Int8
int16Type = reflect.Int16
int32Type = reflect.Int32
int64Type = reflect.Int64
stringType = reflect.String
uintType = reflect.Uint
uint8Type = reflect.Uint8
uint16Type = reflect.Uint16
uint32Type = reflect.Uint32
uint64Type = reflect.Uint64
)
// Default converters for basic types.
var builtinConverters = map[reflect.Kind]Converter{
boolType: convertBool,
float32Type: convertFloat32,
float64Type: convertFloat64,
intType: convertInt,
int8Type: convertInt8,
int16Type: convertInt16,
int32Type: convertInt32,
int64Type: convertInt64,
stringType: convertString,
uintType: convertUint,
uint8Type: convertUint8,
uint16Type: convertUint16,
uint32Type: convertUint32,
uint64Type: convertUint64,
}
func convertBool(value string) reflect.Value {
if value == "on" {
return reflect.ValueOf(true)
} else if v, err := strconv.ParseBool(value); err == nil {
return reflect.ValueOf(v)
}
return invalidValue
}
func convertFloat32(value string) reflect.Value {
if v, err := strconv.ParseFloat(value, 32); err == nil {
return reflect.ValueOf(float32(v))
}
return invalidValue
}
func convertFloat64(value string) reflect.Value {
if v, err := strconv.ParseFloat(value, 64); err == nil {
return reflect.ValueOf(v)
}
return invalidValue
}
func convertInt(value string) reflect.Value {
if v, err := strconv.ParseInt(value, 10, 0); err == nil {
return reflect.ValueOf(int(v))
}
return invalidValue
}
func convertInt8(value string) reflect.Value {
if v, err := strconv.ParseInt(value, 10, 8); err == nil {
return reflect.ValueOf(int8(v))
}
return invalidValue
}
func convertInt16(value string) reflect.Value {
if v, err := strconv.ParseInt(value, 10, 16); err == nil {
return reflect.ValueOf(int16(v))
}
return invalidValue
}
func convertInt32(value string) reflect.Value {
if v, err := strconv.ParseInt(value, 10, 32); err == nil {
return reflect.ValueOf(int32(v))
}
return invalidValue
}
func convertInt64(value string) reflect.Value {
if v, err := strconv.ParseInt(value, 10, 64); err == nil {
return reflect.ValueOf(v)
}
return invalidValue
}
func convertString(value string) reflect.Value {
return reflect.ValueOf(value)
}
func convertUint(value string) reflect.Value {
if v, err := strconv.ParseUint(value, 10, 0); err == nil {
return reflect.ValueOf(uint(v))
}
return invalidValue
}
func convertUint8(value string) reflect.Value {
if v, err := strconv.ParseUint(value, 10, 8); err == nil {
return reflect.ValueOf(uint8(v))
}
return invalidValue
}
func convertUint16(value string) reflect.Value {
if v, err := strconv.ParseUint(value, 10, 16); err == nil {
return reflect.ValueOf(uint16(v))
}
return invalidValue
}
func convertUint32(value string) reflect.Value {
if v, err := strconv.ParseUint(value, 10, 32); err == nil {
return reflect.ValueOf(uint32(v))
}
return invalidValue
}
func convertUint64(value string) reflect.Value {
if v, err := strconv.ParseUint(value, 10, 64); err == nil {
return reflect.ValueOf(v)
}
return invalidValue
}

420
vendor/github.com/gorilla/schema/decoder.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,420 @@
// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package schema
import (
"encoding"
"errors"
"fmt"
"reflect"
"strings"
)
// NewDecoder returns a new Decoder.
func NewDecoder() *Decoder {
return &Decoder{cache: newCache()}
}
// Decoder decodes values from a map[string][]string to a struct.
type Decoder struct {
cache *cache
zeroEmpty bool
ignoreUnknownKeys bool
}
// SetAliasTag changes the tag used to locate custom field aliases.
// The default tag is "schema".
func (d *Decoder) SetAliasTag(tag string) {
d.cache.tag = tag
}
// ZeroEmpty controls the behaviour when the decoder encounters empty values
// in a map.
// If z is true and a key in the map has the empty string as a value
// then the corresponding struct field is set to the zero value.
// If z is false then empty strings are ignored.
//
// The default value is false, that is empty values do not change
// the value of the struct field.
func (d *Decoder) ZeroEmpty(z bool) {
d.zeroEmpty = z
}
// IgnoreUnknownKeys controls the behaviour when the decoder encounters unknown
// keys in the map.
// If i is true and an unknown field is encountered, it is ignored. This is
// similar to how unknown keys are handled by encoding/json.
// If i is false then Decode will return an error. Note that any valid keys
// will still be decoded in to the target struct.
//
// To preserve backwards compatibility, the default value is false.
func (d *Decoder) IgnoreUnknownKeys(i bool) {
d.ignoreUnknownKeys = i
}
// RegisterConverter registers a converter function for a custom type.
func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) {
d.cache.registerConverter(value, converterFunc)
}
// Decode decodes a map[string][]string to a struct.
//
// The first parameter must be a pointer to a struct.
//
// The second parameter is a map, typically url.Values from an HTTP request.
// Keys are "paths" in dotted notation to the struct fields and nested structs.
//
// See the package documentation for a full explanation of the mechanics.
func (d *Decoder) Decode(dst interface{}, src map[string][]string) error {
v := reflect.ValueOf(dst)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
return errors.New("schema: interface must be a pointer to struct")
}
v = v.Elem()
t := v.Type()
errors := MultiError{}
for path, values := range src {
if parts, err := d.cache.parsePath(path, t); err == nil {
if err = d.decode(v, path, parts, values); err != nil {
errors[path] = err
}
} else if !d.ignoreUnknownKeys {
errors[path] = fmt.Errorf("schema: invalid path %q", path)
}
}
if len(errors) > 0 {
return errors
}
return d.checkRequired(t, src, "")
}
// checkRequired checks whether required fields are empty
//
// check type t recursively if t has struct fields, and prefix is same as parsePath: in dotted notation
//
// src is the source map for decoding, we use it here to see if those required fields are included in src
func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string, prefix string) error {
struc := d.cache.get(t)
if struc == nil {
// unexpect, cache.get never return nil
return errors.New("cache fail")
}
for _, f := range struc.fields {
if f.typ.Kind() == reflect.Struct {
err := d.checkRequired(f.typ, src, prefix+f.alias+".")
if err != nil {
if !f.anon {
return err
}
// check embedded parent field.
err2 := d.checkRequired(f.typ, src, prefix)
if err2 != nil {
return err
}
}
}
if f.required {
key := f.alias
if prefix != "" {
key = prefix + key
}
if isEmpty(f.typ, src[key]) {
return fmt.Errorf("%v is empty", key)
}
}
}
return nil
}
// isEmpty returns true if value is empty for specific type
func isEmpty(t reflect.Type, value []string) bool {
if len(value) == 0 {
return true
}
switch t.Kind() {
case boolType, float32Type, float64Type, intType, int8Type, int32Type, int64Type, stringType, uint8Type, uint16Type, uint32Type, uint64Type:
return len(value[0]) == 0
}
return false
}
// decode fills a struct field using a parsed path.
func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values []string) error {
// Get the field walking the struct fields by index.
for _, name := range parts[0].path {
if v.Type().Kind() == reflect.Ptr {
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
v = v.Elem()
}
v = v.FieldByName(name)
}
// Don't even bother for unexported fields.
if !v.CanSet() {
return nil
}
// Dereference if needed.
t := v.Type()
if t.Kind() == reflect.Ptr {
t = t.Elem()
if v.IsNil() {
v.Set(reflect.New(t))
}
v = v.Elem()
}
// Slice of structs. Let's go recursive.
if len(parts) > 1 {
idx := parts[0].index
if v.IsNil() || v.Len() < idx+1 {
value := reflect.MakeSlice(t, idx+1, idx+1)
if v.Len() < idx+1 {
// Resize it.
reflect.Copy(value, v)
}
v.Set(value)
}
return d.decode(v.Index(idx), path, parts[1:], values)
}
// Get the converter early in case there is one for a slice type.
conv := d.cache.converter(t)
m := isTextUnmarshaler(v)
if conv == nil && t.Kind() == reflect.Slice && m.IsSlice {
var items []reflect.Value
elemT := t.Elem()
isPtrElem := elemT.Kind() == reflect.Ptr
if isPtrElem {
elemT = elemT.Elem()
}
// Try to get a converter for the element type.
conv := d.cache.converter(elemT)
if conv == nil {
conv = builtinConverters[elemT.Kind()]
if conv == nil {
// As we are not dealing with slice of structs here, we don't need to check if the type
// implements TextUnmarshaler interface
return fmt.Errorf("schema: converter not found for %v", elemT)
}
}
for key, value := range values {
if value == "" {
if d.zeroEmpty {
items = append(items, reflect.Zero(elemT))
}
} else if m.IsValid {
u := reflect.New(elemT)
if m.IsPtr {
u = reflect.New(reflect.PtrTo(elemT).Elem())
}
if err := u.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(value)); err != nil {
return ConversionError{
Key: path,
Type: t,
Index: key,
Err: err,
}
}
if m.IsPtr {
items = append(items, u.Elem().Addr())
} else if u.Kind() == reflect.Ptr {
items = append(items, u.Elem())
} else {
items = append(items, u)
}
} else if item := conv(value); item.IsValid() {
if isPtrElem {
ptr := reflect.New(elemT)
ptr.Elem().Set(item)
item = ptr
}
if item.Type() != elemT && !isPtrElem {
item = item.Convert(elemT)
}
items = append(items, item)
} else {
if strings.Contains(value, ",") {
values := strings.Split(value, ",")
for _, value := range values {
if value == "" {
if d.zeroEmpty {
items = append(items, reflect.Zero(elemT))
}
} else if item := conv(value); item.IsValid() {
if isPtrElem {
ptr := reflect.New(elemT)
ptr.Elem().Set(item)
item = ptr
}
if item.Type() != elemT && !isPtrElem {
item = item.Convert(elemT)
}
items = append(items, item)
} else {
return ConversionError{
Key: path,
Type: elemT,
Index: key,
}
}
}
} else {
return ConversionError{
Key: path,
Type: elemT,
Index: key,
}
}
}
}
value := reflect.Append(reflect.MakeSlice(t, 0, 0), items...)
v.Set(value)
} else {
val := ""
// Use the last value provided if any values were provided
if len(values) > 0 {
val = values[len(values)-1]
}
if val == "" {
if d.zeroEmpty {
v.Set(reflect.Zero(t))
}
} else if conv != nil {
if value := conv(val); value.IsValid() {
v.Set(value.Convert(t))
} else {
return ConversionError{
Key: path,
Type: t,
Index: -1,
}
}
} else if m.IsValid {
// If the value implements the encoding.TextUnmarshaler interface
// apply UnmarshalText as the converter
if err := m.Unmarshaler.UnmarshalText([]byte(val)); err != nil {
return ConversionError{
Key: path,
Type: t,
Index: -1,
Err: err,
}
}
} else if conv := builtinConverters[t.Kind()]; conv != nil {
if value := conv(val); value.IsValid() {
v.Set(value.Convert(t))
} else {
return ConversionError{
Key: path,
Type: t,
Index: -1,
}
}
} else {
return fmt.Errorf("schema: converter not found for %v", t)
}
}
return nil
}
func isTextUnmarshaler(v reflect.Value) unmarshaler {
// Create a new unmarshaller instance
m := unmarshaler{}
// As the UnmarshalText function should be applied
// to the pointer of the type, we convert the value to pointer.
if v.CanAddr() {
v = v.Addr()
}
if m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler); m.IsValid {
return m
}
// if v is []T or *[]T create new T
t := v.Type()
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() == reflect.Slice {
// if t is a pointer slice, check if it implements encoding.TextUnmarshaler
m.IsSlice = true
if t = t.Elem(); t.Kind() == reflect.Ptr {
t = reflect.PtrTo(t.Elem())
v = reflect.Zero(t)
m.IsPtr = true
m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler)
return m
}
}
v = reflect.New(t)
m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler)
return m
}
// TextUnmarshaler helpers ----------------------------------------------------
// unmarshaller contains information about a TextUnmarshaler type
type unmarshaler struct {
Unmarshaler encoding.TextUnmarshaler
IsSlice bool
IsPtr bool
IsValid bool
}
// Errors ---------------------------------------------------------------------
// ConversionError stores information about a failed conversion.
type ConversionError struct {
Key string // key from the source map.
Type reflect.Type // expected type of elem
Index int // index for multi-value fields; -1 for single-value fields.
Err error // low-level error (when it exists)
}
func (e ConversionError) Error() string {
var output string
if e.Index < 0 {
output = fmt.Sprintf("schema: error converting value for %q", e.Key)
} else {
output = fmt.Sprintf("schema: error converting value for index %d of %q",
e.Index, e.Key)
}
if e.Err != nil {
output = fmt.Sprintf("%s. Details: %s", output, e.Err)
}
return output
}
// MultiError stores multiple decoding errors.
//
// Borrowed from the App Engine SDK.
type MultiError map[string]error
func (e MultiError) Error() string {
s := ""
for _, err := range e {
s = err.Error()
break
}
switch len(e) {
case 0:
return "(0 errors)"
case 1:
return s
case 2:
return s + " (and 1 other error)"
}
return fmt.Sprintf("%s (and %d other errors)", s, len(e)-1)
}

1693
vendor/github.com/gorilla/schema/decoder_test.go сгенерированный поставляемый Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

148
vendor/github.com/gorilla/schema/doc.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,148 @@
// Copyright 2012 The Gorilla Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package gorilla/schema fills a struct with form values.
The basic usage is really simple. Given this struct:
type Person struct {
Name string
Phone string
}
...we can fill it passing a map to the Decode() function:
values := map[string][]string{
"Name": {"John"},
"Phone": {"999-999-999"},
}
person := new(Person)
decoder := schema.NewDecoder()
decoder.Decode(person, values)
This is just a simple example and it doesn't make a lot of sense to create
the map manually. Typically it will come from a http.Request object and
will be of type url.Values, http.Request.Form, or http.Request.MultipartForm:
func MyHandler(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
// Handle error
}
decoder := schema.NewDecoder()
// r.PostForm is a map of our POST form values
err := decoder.Decode(person, r.PostForm)
if err != nil {
// Handle error
}
// Do something with person.Name or person.Phone
}
Note: it is a good idea to set a Decoder instance as a package global,
because it caches meta-data about structs, and an instance can be shared safely:
var decoder = schema.NewDecoder()
To define custom names for fields, use a struct tag "schema". To not populate
certain fields, use a dash for the name and it will be ignored:
type Person struct {
Name string `schema:"name"` // custom name
Phone string `schema:"phone"` // custom name
Admin bool `schema:"-"` // this field is never set
}
The supported field types in the destination struct are:
* bool
* float variants (float32, float64)
* int variants (int, int8, int16, int32, int64)
* string
* uint variants (uint, uint8, uint16, uint32, uint64)
* struct
* a pointer to one of the above types
* a slice or a pointer to a slice of one of the above types
Non-supported types are simply ignored, however custom types can be registered
to be converted.
To fill nested structs, keys must use a dotted notation as the "path" for the
field. So for example, to fill the struct Person below:
type Phone struct {
Label string
Number string
}
type Person struct {
Name string
Phone Phone
}
...the source map must have the keys "Name", "Phone.Label" and "Phone.Number".
This means that an HTML form to fill a Person struct must look like this:
<form>
<input type="text" name="Name">
<input type="text" name="Phone.Label">
<input type="text" name="Phone.Number">
</form>
Single values are filled using the first value for a key from the source map.
Slices are filled using all values for a key from the source map. So to fill
a Person with multiple Phone values, like:
type Person struct {
Name string
Phones []Phone
}
...an HTML form that accepts three Phone values would look like this:
<form>
<input type="text" name="Name">
<input type="text" name="Phones.0.Label">
<input type="text" name="Phones.0.Number">
<input type="text" name="Phones.1.Label">
<input type="text" name="Phones.1.Number">
<input type="text" name="Phones.2.Label">
<input type="text" name="Phones.2.Number">
</form>
Notice that only for slices of structs the slice index is required.
This is needed for disambiguation: if the nested struct also had a slice
field, we could not translate multiple values to it if we did not use an
index for the parent struct.
There's also the possibility to create a custom type that implements the
TextUnmarshaler interface, and in this case there's no need to register
a converter, like:
type Person struct {
Emails []Email
}
type Email struct {
*mail.Address
}
func (e *Email) UnmarshalText(text []byte) (err error) {
e.Address, err = mail.ParseAddress(string(text))
return
}
...an HTML form that accepts three Email values would look like this:
<form>
<input type="email" name="Emails.0">
<input type="email" name="Emails.1">
<input type="email" name="Emails.2">
</form>
*/
package schema

195
vendor/github.com/gorilla/schema/encoder.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,195 @@
package schema
import (
"errors"
"fmt"
"reflect"
"strconv"
)
type encoderFunc func(reflect.Value) string
// Encoder encodes values from a struct into url.Values.
type Encoder struct {
cache *cache
regenc map[reflect.Type]encoderFunc
}
// NewEncoder returns a new Encoder with defaults.
func NewEncoder() *Encoder {
return &Encoder{cache: newCache(), regenc: make(map[reflect.Type]encoderFunc)}
}
// Encode encodes a struct into map[string][]string.
//
// Intended for use with url.Values.
func (e *Encoder) Encode(src interface{}, dst map[string][]string) error {
v := reflect.ValueOf(src)
return e.encode(v, dst)
}
// RegisterEncoder registers a converter for encoding a custom type.
func (e *Encoder) RegisterEncoder(value interface{}, encoder func(reflect.Value) string) {
e.regenc[reflect.TypeOf(value)] = encoder
}
// SetAliasTag changes the tag used to locate custom field aliases.
// The default tag is "schema".
func (e *Encoder) SetAliasTag(tag string) {
e.cache.tag = tag
}
// isValidStructPointer test if input value is a valid struct pointer.
func isValidStructPointer(v reflect.Value) bool {
return v.Type().Kind() == reflect.Ptr && v.Elem().IsValid() && v.Elem().Type().Kind() == reflect.Struct
}
func isZero(v reflect.Value) bool {
switch v.Kind() {
case reflect.Func:
case reflect.Map, reflect.Slice:
return v.IsNil() || v.Len() == 0
case reflect.Array:
z := true
for i := 0; i < v.Len(); i++ {
z = z && isZero(v.Index(i))
}
return z
case reflect.Struct:
z := true
for i := 0; i < v.NumField(); i++ {
z = z && isZero(v.Field(i))
}
return z
}
// Compare other types directly:
z := reflect.Zero(v.Type())
return v.Interface() == z.Interface()
}
func (e *Encoder) encode(v reflect.Value, dst map[string][]string) error {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return errors.New("schema: interface must be a struct")
}
t := v.Type()
errors := MultiError{}
for i := 0; i < v.NumField(); i++ {
name, opts := fieldAlias(t.Field(i), e.cache.tag)
if name == "-" {
continue
}
// Encode struct pointer types if the field is a valid pointer and a struct.
if isValidStructPointer(v.Field(i)) {
e.encode(v.Field(i).Elem(), dst)
continue
}
encFunc := typeEncoder(v.Field(i).Type(), e.regenc)
// Encode non-slice types and custom implementations immediately.
if encFunc != nil {
value := encFunc(v.Field(i))
if opts.Contains("omitempty") && isZero(v.Field(i)) {
continue
}
dst[name] = append(dst[name], value)
continue
}
if v.Field(i).Type().Kind() == reflect.Struct {
e.encode(v.Field(i), dst)
continue
}
if v.Field(i).Type().Kind() == reflect.Slice {
encFunc = typeEncoder(v.Field(i).Type().Elem(), e.regenc)
}
if encFunc == nil {
errors[v.Field(i).Type().String()] = fmt.Errorf("schema: encoder not found for %v", v.Field(i))
continue
}
// Encode a slice.
if v.Field(i).Len() == 0 && opts.Contains("omitempty") {
continue
}
dst[name] = []string{}
for j := 0; j < v.Field(i).Len(); j++ {
dst[name] = append(dst[name], encFunc(v.Field(i).Index(j)))
}
}
if len(errors) > 0 {
return errors
}
return nil
}
func typeEncoder(t reflect.Type, reg map[reflect.Type]encoderFunc) encoderFunc {
if f, ok := reg[t]; ok {
return f
}
switch t.Kind() {
case reflect.Bool:
return encodeBool
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return encodeInt
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return encodeUint
case reflect.Float32:
return encodeFloat32
case reflect.Float64:
return encodeFloat64
case reflect.Ptr:
f := typeEncoder(t.Elem(), reg)
return func(v reflect.Value) string {
if v.IsNil() {
return "null"
}
return f(v.Elem())
}
case reflect.String:
return encodeString
default:
return nil
}
}
func encodeBool(v reflect.Value) string {
return strconv.FormatBool(v.Bool())
}
func encodeInt(v reflect.Value) string {
return strconv.FormatInt(int64(v.Int()), 10)
}
func encodeUint(v reflect.Value) string {
return strconv.FormatUint(uint64(v.Uint()), 10)
}
func encodeFloat(v reflect.Value, bits int) string {
return strconv.FormatFloat(v.Float(), 'f', 6, bits)
}
func encodeFloat32(v reflect.Value) string {
return encodeFloat(v, 32)
}
func encodeFloat64(v reflect.Value) string {
return encodeFloat(v, 64)
}
func encodeString(v reflect.Value) string {
return v.String()
}

420
vendor/github.com/gorilla/schema/encoder_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,420 @@
package schema
import (
"fmt"
"reflect"
"testing"
)
type E1 struct {
F01 int `schema:"f01"`
F02 int `schema:"-"`
F03 string `schema:"f03"`
F04 string `schema:"f04,omitempty"`
F05 bool `schema:"f05"`
F06 bool `schema:"f06"`
F07 *string `schema:"f07"`
F08 *int8 `schema:"f08"`
F09 float64 `schema:"f09"`
F10 func() `schema:"f10"`
F11 inner
}
type inner struct {
F12 int
}
func TestFilled(t *testing.T) {
f07 := "seven"
var f08 int8 = 8
s := &E1{
F01: 1,
F02: 2,
F03: "three",
F04: "four",
F05: true,
F06: false,
F07: &f07,
F08: &f08,
F09: 1.618,
F10: func() {},
F11: inner{12},
}
vals := make(map[string][]string)
errs := NewEncoder().Encode(s, vals)
valExists(t, "f01", "1", vals)
valNotExists(t, "f02", vals)
valExists(t, "f03", "three", vals)
valExists(t, "f05", "true", vals)
valExists(t, "f06", "false", vals)
valExists(t, "f07", "seven", vals)
valExists(t, "f08", "8", vals)
valExists(t, "f09", "1.618000", vals)
valExists(t, "F12", "12", vals)
emptyErr := MultiError{}
if errs.Error() == emptyErr.Error() {
t.Errorf("Expected error got %v", errs)
}
}
type Aa int
type E3 struct {
F01 bool `schema:"f01"`
F02 float32 `schema:"f02"`
F03 float64 `schema:"f03"`
F04 int `schema:"f04"`
F05 int8 `schema:"f05"`
F06 int16 `schema:"f06"`
F07 int32 `schema:"f07"`
F08 int64 `schema:"f08"`
F09 string `schema:"f09"`
F10 uint `schema:"f10"`
F11 uint8 `schema:"f11"`
F12 uint16 `schema:"f12"`
F13 uint32 `schema:"f13"`
F14 uint64 `schema:"f14"`
F15 Aa `schema:"f15"`
}
// Test compatibility with default decoder types.
func TestCompat(t *testing.T) {
src := &E3{
F01: true,
F02: 4.2,
F03: 4.3,
F04: -42,
F05: -43,
F06: -44,
F07: -45,
F08: -46,
F09: "foo",
F10: 42,
F11: 43,
F12: 44,
F13: 45,
F14: 46,
F15: 1,
}
dst := &E3{}
vals := make(map[string][]string)
encoder := NewEncoder()
decoder := NewDecoder()
encoder.RegisterEncoder(src.F15, func(reflect.Value) string { return "1" })
decoder.RegisterConverter(src.F15, func(string) reflect.Value { return reflect.ValueOf(1) })
err := encoder.Encode(src, vals)
if err != nil {
t.Errorf("Encoder has non-nil error: %v", err)
}
err = decoder.Decode(dst, vals)
if err != nil {
t.Errorf("Decoder has non-nil error: %v", err)
}
if *src != *dst {
t.Errorf("Decoder-Encoder compatibility: expected %v, got %v\n", src, dst)
}
}
func TestEmpty(t *testing.T) {
s := &E1{
F01: 1,
F02: 2,
F03: "three",
}
estr := "schema: encoder not found for <nil>"
vals := make(map[string][]string)
err := NewEncoder().Encode(s, vals)
if err.Error() != estr {
t.Errorf("Expected: %s, got %v", estr, err)
}
valExists(t, "f03", "three", vals)
valNotExists(t, "f04", vals)
}
func TestStruct(t *testing.T) {
estr := "schema: interface must be a struct"
vals := make(map[string][]string)
err := NewEncoder().Encode("hello world", vals)
if err.Error() != estr {
t.Errorf("Expected: %s, got %v", estr, err)
}
}
func TestSlices(t *testing.T) {
type oneAsWord int
ones := []oneAsWord{1, 2}
s1 := &struct {
ones []oneAsWord `schema:"ones"`
ints []int `schema:"ints"`
nonempty []int `schema:"nonempty"`
empty []int `schema:"empty,omitempty"`
}{ones, []int{1, 1}, []int{}, []int{}}
vals := make(map[string][]string)
encoder := NewEncoder()
encoder.RegisterEncoder(ones[0], func(v reflect.Value) string { return "one" })
err := encoder.Encode(s1, vals)
if err != nil {
t.Errorf("Encoder has non-nil error: %v", err)
}
valsExist(t, "ones", []string{"one", "one"}, vals)
valsExist(t, "ints", []string{"1", "1"}, vals)
valsExist(t, "nonempty", []string{}, vals)
valNotExists(t, "empty", vals)
}
func TestCompatSlices(t *testing.T) {
type oneAsWord int
type s1 struct {
Ones []oneAsWord `schema:"ones"`
Ints []int `schema:"ints"`
}
ones := []oneAsWord{1, 1}
src := &s1{ones, []int{1, 1}}
vals := make(map[string][]string)
dst := &s1{}
encoder := NewEncoder()
encoder.RegisterEncoder(ones[0], func(v reflect.Value) string { return "one" })
decoder := NewDecoder()
decoder.RegisterConverter(ones[0], func(s string) reflect.Value {
if s == "one" {
return reflect.ValueOf(1)
}
return reflect.ValueOf(2)
})
err := encoder.Encode(src, vals)
if err != nil {
t.Errorf("Encoder has non-nil error: %v", err)
}
err = decoder.Decode(dst, vals)
if err != nil {
t.Errorf("Dncoder has non-nil error: %v", err)
}
if len(src.Ints) != len(dst.Ints) || len(src.Ones) != len(src.Ones) {
t.Fatalf("Expected %v, got %v", src, dst)
}
for i, v := range src.Ones {
if dst.Ones[i] != v {
t.Fatalf("Expected %v, got %v", v, dst.Ones[i])
}
}
for i, v := range src.Ints {
if dst.Ints[i] != v {
t.Fatalf("Expected %v, got %v", v, dst.Ints[i])
}
}
}
func TestRegisterEncoder(t *testing.T) {
type oneAsWord int
type twoAsWord int
type oneSliceAsWord []int
s1 := &struct {
oneAsWord
twoAsWord
oneSliceAsWord
}{1, 2, []int{1, 1}}
v1 := make(map[string][]string)
encoder := NewEncoder()
encoder.RegisterEncoder(s1.oneAsWord, func(v reflect.Value) string { return "one" })
encoder.RegisterEncoder(s1.twoAsWord, func(v reflect.Value) string { return "two" })
encoder.RegisterEncoder(s1.oneSliceAsWord, func(v reflect.Value) string { return "one" })
err := encoder.Encode(s1, v1)
if err != nil {
t.Errorf("Encoder has non-nil error: %v", err)
}
valExists(t, "oneAsWord", "one", v1)
valExists(t, "twoAsWord", "two", v1)
valExists(t, "oneSliceAsWord", "one", v1)
}
func TestEncoderOrder(t *testing.T) {
type builtinEncoderSimple int
type builtinEncoderSimpleOverridden int
type builtinEncoderSlice []int
type builtinEncoderSliceOverridden []int
type builtinEncoderStruct struct{ nr int }
type builtinEncoderStructOverridden struct{ nr int }
s1 := &struct {
builtinEncoderSimple `schema:"simple"`
builtinEncoderSimpleOverridden `schema:"simple_overridden"`
builtinEncoderSlice `schema:"slice"`
builtinEncoderSliceOverridden `schema:"slice_overridden"`
builtinEncoderStruct `schema:"struct"`
builtinEncoderStructOverridden `schema:"struct_overridden"`
}{
1,
1,
[]int{2},
[]int{2},
builtinEncoderStruct{3},
builtinEncoderStructOverridden{3},
}
v1 := make(map[string][]string)
encoder := NewEncoder()
encoder.RegisterEncoder(s1.builtinEncoderSimpleOverridden, func(v reflect.Value) string { return "one" })
encoder.RegisterEncoder(s1.builtinEncoderSliceOverridden, func(v reflect.Value) string { return "two" })
encoder.RegisterEncoder(s1.builtinEncoderStructOverridden, func(v reflect.Value) string { return "three" })
err := encoder.Encode(s1, v1)
if err != nil {
t.Errorf("Encoder has non-nil error: %v", err)
}
valExists(t, "simple", "1", v1)
valExists(t, "simple_overridden", "one", v1)
valExists(t, "slice", "2", v1)
valExists(t, "slice_overridden", "two", v1)
valExists(t, "nr", "3", v1)
valExists(t, "struct_overridden", "three", v1)
}
func valExists(t *testing.T, key string, expect string, result map[string][]string) {
valsExist(t, key, []string{expect}, result)
}
func valsExist(t *testing.T, key string, expect []string, result map[string][]string) {
vals, ok := result[key]
if !ok {
t.Fatalf("Key not found. Expected: %s", key)
}
if len(expect) != len(vals) {
t.Fatalf("Expected: %v, got: %v", expect, vals)
}
for i, v := range expect {
if vals[i] != v {
t.Fatalf("Unexpected value. Expected: %v, got %v", v, vals[i])
}
}
}
func valNotExists(t *testing.T, key string, result map[string][]string) {
if val, ok := result[key]; ok {
t.Error("Key not ommited. Expected: empty; got: " + val[0] + ".")
}
}
type E4 struct {
ID string `json:"id"`
}
func TestEncoderSetAliasTag(t *testing.T) {
data := map[string][]string{}
s := E4{
ID: "foo",
}
encoder := NewEncoder()
encoder.SetAliasTag("json")
encoder.Encode(&s, data)
valExists(t, "id", "foo", data)
}
type E5 struct {
F01 int `schema:"f01,omitempty"`
F02 string `schema:"f02,omitempty"`
F03 *string `schema:"f03,omitempty"`
F04 *int8 `schema:"f04,omitempty"`
F05 float64 `schema:"f05,omitempty"`
F06 E5F06 `schema:"f06,omitempty"`
F07 E5F06 `schema:"f07,omitempty"`
F08 []string `schema:"f08,omitempty"`
F09 []string `schema:"f09,omitempty"`
}
type E5F06 struct {
F0601 string `schema:"f0601,omitempty"`
}
func TestEncoderWithOmitempty(t *testing.T) {
vals := map[string][]string{}
s := E5{
F02: "test",
F07: E5F06{
F0601: "test",
},
F09: []string{"test"},
}
encoder := NewEncoder()
encoder.Encode(&s, vals)
valNotExists(t, "f01", vals)
valExists(t, "f02", "test", vals)
valNotExists(t, "f03", vals)
valNotExists(t, "f04", vals)
valNotExists(t, "f05", vals)
valNotExists(t, "f06", vals)
valExists(t, "f0601", "test", vals)
valNotExists(t, "f08", vals)
valsExist(t, "f09", []string{"test"}, vals)
}
type E6 struct {
F01 *inner
F02 *inner
F03 *inner `schema:",omitempty"`
}
func TestStructPointer(t *testing.T) {
vals := map[string][]string{}
s := E6{
F01: &inner{2},
}
encoder := NewEncoder()
encoder.Encode(&s, vals)
valExists(t, "F12", "2", vals)
valExists(t, "F02", "null", vals)
valNotExists(t, "F03", vals)
}
func TestRegisterEncoderCustomArrayType(t *testing.T) {
type CustomInt []int
type S1 struct {
SomeInts CustomInt `schema:",omitempty"`
}
ss := []S1{
{},
{CustomInt{}},
{CustomInt{1, 2, 3}},
}
for s := range ss {
vals := map[string][]string{}
encoder := NewEncoder()
encoder.RegisterEncoder(CustomInt{}, func(value reflect.Value) string {
return fmt.Sprint(value.Interface())
})
encoder.Encode(s, vals)
t.Log(vals)
}
}

15
vendor/github.com/gorilla/websocket/conn.go сгенерированный поставляемый
Просмотреть файл

@@ -1051,8 +1051,9 @@ func (c *Conn) CloseHandler() func(code int, text string) error {
// if the close message is empty. The default close handler sends a close
// message back to the peer.
//
// The application must read the connection to process close messages as
// described in the section on Control Messages above.
// The handler function is called from the NextReader, ReadMessage and message
// reader Read methods. The application must read the connection to process
// close messages as described in the section on Control Messages above.
//
// The connection read methods return a CloseError when a close message is
// received. Most applications should handle close messages as part of their
@@ -1079,8 +1080,9 @@ func (c *Conn) PingHandler() func(appData string) error {
// The appData argument to h is the PING message application data. The default
// ping handler sends a pong to the peer.
//
// The application must read the connection to process ping messages as
// described in the section on Control Messages above.
// The handler function is called from the NextReader, ReadMessage and message
// reader Read methods. The application must read the connection to process
// ping messages as described in the section on Control Messages above.
func (c *Conn) SetPingHandler(h func(appData string) error) {
if h == nil {
h = func(message string) error {
@@ -1105,8 +1107,9 @@ func (c *Conn) PongHandler() func(appData string) error {
// The appData argument to h is the PONG message application data. The default
// pong handler does nothing.
//
// The application must read the connection to process ping messages as
// described in the section on Control Messages above.
// The handler function is called from the NextReader, ReadMessage and message
// reader Read methods. The application must read the connection to process
// pong messages as described in the section on Control Messages above.
func (c *Conn) SetPongHandler(h func(appData string) error) {
if h == nil {
h = func(string) error { return nil }