mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-08-12 21:58:10 +00:00
Vendor libs
This commit is contained in:
27
vendor/github.com/gorilla/schema/LICENSE
generated
vendored
Normal file
27
vendor/github.com/gorilla/schema/LICENSE
generated
vendored
Normal file
@@ -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.
|
245
vendor/github.com/gorilla/schema/cache.go
generated
vendored
Normal file
245
vendor/github.com/gorilla/schema/cache.go
generated
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
// 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),
|
||||
conv: make(map[reflect.Kind]Converter),
|
||||
regconv: make(map[reflect.Type]Converter),
|
||||
tag: "schema",
|
||||
}
|
||||
for k, v := range converters {
|
||||
c.conv[k] = v
|
||||
}
|
||||
return &c
|
||||
}
|
||||
|
||||
// cache caches meta-data about a struct.
|
||||
type cache struct {
|
||||
l sync.RWMutex
|
||||
m map[reflect.Type]*structInfo
|
||||
conv map[reflect.Kind]Converter
|
||||
regconv map[reflect.Type]Converter
|
||||
tag string
|
||||
}
|
||||
|
||||
// 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 {
|
||||
c.create(ft, info)
|
||||
}
|
||||
}
|
||||
c.createField(field, info)
|
||||
}
|
||||
return info
|
||||
}
|
||||
|
||||
// createField creates a fieldInfo for the given field.
|
||||
func (c *cache) createField(field reflect.StructField, info *structInfo) {
|
||||
alias := 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 conv := c.conv[ft.Kind()]; conv == nil {
|
||||
// Type is not supported.
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
info.fields = append(info.fields, &fieldInfo{
|
||||
typ: field.Type,
|
||||
name: field.Name,
|
||||
ss: isSlice && isStruct,
|
||||
alias: alias,
|
||||
})
|
||||
}
|
||||
|
||||
// converter returns the converter for a type.
|
||||
func (c *cache) converter(t reflect.Type) Converter {
|
||||
conv := c.regconv[t]
|
||||
if conv == nil {
|
||||
conv = c.conv[t.Kind()]
|
||||
}
|
||||
return conv
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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) string {
|
||||
var alias string
|
||||
if tag := field.Tag.Get(tagName); tag != "" {
|
||||
// For now tags only support the name but let's follow the
|
||||
// comma convention from encoding/json and others.
|
||||
if idx := strings.Index(tag, ","); idx == -1 {
|
||||
alias = tag
|
||||
} else {
|
||||
alias = tag[:idx]
|
||||
}
|
||||
}
|
||||
if alias == "" {
|
||||
alias = field.Name
|
||||
}
|
||||
return alias
|
||||
}
|
145
vendor/github.com/gorilla/schema/converter.go
generated
vendored
Normal file
145
vendor/github.com/gorilla/schema/converter.go
generated
vendored
Normal file
@@ -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 converters = 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
|
||||
}
|
299
vendor/github.com/gorilla/schema/decoder.go
generated
vendored
Normal file
299
vendor/github.com/gorilla/schema/decoder.go
generated
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
// 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.regconv[reflect.TypeOf(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 nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if conv == nil && t.Kind() == reflect.Slice {
|
||||
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 {
|
||||
// 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 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 {
|
||||
// When there's no registered conversion for the custom type, we will check if the type
|
||||
// implements the TextUnmarshaler interface. 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 u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
|
||||
if err := u.UnmarshalText([]byte(val)); err != nil {
|
||||
return ConversionError{
|
||||
Key: path,
|
||||
Type: t,
|
||||
Index: -1,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
return fmt.Errorf("schema: converter not found for %v", t)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
148
vendor/github.com/gorilla/schema/doc.go
generated
vendored
Normal file
148
vendor/github.com/gorilla/schema/doc.go
generated
vendored
Normal file
@@ -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 Load() 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 a 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 registry
|
||||
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
|
Reference in New Issue
Block a user