mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[feature] Add support for profile fields (#1483)
* Add go-playground/form pkg * [feature] Add support for profile fields * Add field attributes test * Validate profile fields form * Add profile field validation tests * Add Field Attributes definition to swagger --------- Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
This commit is contained in:
261
vendor/github.com/go-playground/form/v4/encoder.go
generated
vendored
Normal file
261
vendor/github.com/go-playground/form/v4/encoder.go
generated
vendored
Normal file
@ -0,0 +1,261 @@
|
||||
package form
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
e *Encoder
|
||||
errs EncodeErrors
|
||||
values url.Values
|
||||
namespace []byte
|
||||
}
|
||||
|
||||
func (e *encoder) setError(namespace []byte, err error) {
|
||||
if e.errs == nil {
|
||||
e.errs = make(EncodeErrors)
|
||||
}
|
||||
|
||||
e.errs[string(namespace)] = err
|
||||
}
|
||||
|
||||
func (e *encoder) setVal(namespace []byte, idx int, vals ...string) {
|
||||
|
||||
arr, ok := e.values[string(namespace)]
|
||||
if ok {
|
||||
arr = append(arr, vals...)
|
||||
} else {
|
||||
arr = vals
|
||||
}
|
||||
|
||||
e.values[string(namespace)] = arr
|
||||
}
|
||||
|
||||
func (e *encoder) traverseStruct(v reflect.Value, namespace []byte, idx int) {
|
||||
|
||||
typ := v.Type()
|
||||
l := len(namespace)
|
||||
first := l == 0
|
||||
|
||||
// anonymous structs will still work for caching as the whole definition is stored
|
||||
// including tags
|
||||
s, ok := e.e.structCache.Get(typ)
|
||||
if !ok {
|
||||
s = e.e.structCache.parseStruct(e.e.mode, v, typ, e.e.tagName)
|
||||
}
|
||||
|
||||
for _, f := range s.fields {
|
||||
namespace = namespace[:l]
|
||||
|
||||
if f.isAnonymous && e.e.embedAnonymous {
|
||||
e.setFieldByType(v.Field(f.idx), namespace, idx, f.isOmitEmpty)
|
||||
continue
|
||||
}
|
||||
|
||||
if first {
|
||||
namespace = append(namespace, f.name...)
|
||||
} else {
|
||||
namespace = append(namespace, e.e.namespacePrefix...)
|
||||
namespace = append(namespace, f.name...)
|
||||
namespace = append(namespace, e.e.namespaceSuffix...)
|
||||
}
|
||||
|
||||
e.setFieldByType(v.Field(f.idx), namespace, idx, f.isOmitEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) setFieldByType(current reflect.Value, namespace []byte, idx int, isOmitEmpty bool) {
|
||||
|
||||
if idx > -1 && current.Kind() == reflect.Ptr {
|
||||
namespace = append(namespace, '[')
|
||||
namespace = strconv.AppendInt(namespace, int64(idx), 10)
|
||||
namespace = append(namespace, ']')
|
||||
idx = -2
|
||||
}
|
||||
|
||||
if isOmitEmpty && !hasValue(current) {
|
||||
return
|
||||
}
|
||||
v, kind := ExtractType(current)
|
||||
|
||||
if e.e.customTypeFuncs != nil {
|
||||
|
||||
if cf, ok := e.e.customTypeFuncs[v.Type()]; ok {
|
||||
|
||||
arr, err := cf(v.Interface())
|
||||
if err != nil {
|
||||
e.setError(namespace, err)
|
||||
return
|
||||
}
|
||||
|
||||
if idx > -1 {
|
||||
namespace = append(namespace, '[')
|
||||
namespace = strconv.AppendInt(namespace, int64(idx), 10)
|
||||
namespace = append(namespace, ']')
|
||||
}
|
||||
|
||||
e.setVal(namespace, idx, arr...)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.Ptr, reflect.Interface, reflect.Invalid:
|
||||
return
|
||||
|
||||
case reflect.String:
|
||||
|
||||
e.setVal(namespace, idx, v.String())
|
||||
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
|
||||
e.setVal(namespace, idx, strconv.FormatUint(v.Uint(), 10))
|
||||
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
|
||||
e.setVal(namespace, idx, strconv.FormatInt(v.Int(), 10))
|
||||
|
||||
case reflect.Float32:
|
||||
|
||||
e.setVal(namespace, idx, strconv.FormatFloat(v.Float(), 'f', -1, 32))
|
||||
|
||||
case reflect.Float64:
|
||||
|
||||
e.setVal(namespace, idx, strconv.FormatFloat(v.Float(), 'f', -1, 64))
|
||||
|
||||
case reflect.Bool:
|
||||
|
||||
e.setVal(namespace, idx, strconv.FormatBool(v.Bool()))
|
||||
|
||||
case reflect.Slice, reflect.Array:
|
||||
|
||||
if idx == -1 {
|
||||
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
e.setFieldByType(v.Index(i), namespace, i, false)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if idx > -1 {
|
||||
namespace = append(namespace, '[')
|
||||
namespace = strconv.AppendInt(namespace, int64(idx), 10)
|
||||
namespace = append(namespace, ']')
|
||||
}
|
||||
|
||||
namespace = append(namespace, '[')
|
||||
l := len(namespace)
|
||||
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
namespace = namespace[:l]
|
||||
namespace = strconv.AppendInt(namespace, int64(i), 10)
|
||||
namespace = append(namespace, ']')
|
||||
e.setFieldByType(v.Index(i), namespace, -2, false)
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
|
||||
if idx > -1 {
|
||||
namespace = append(namespace, '[')
|
||||
namespace = strconv.AppendInt(namespace, int64(idx), 10)
|
||||
namespace = append(namespace, ']')
|
||||
}
|
||||
|
||||
var valid bool
|
||||
var s string
|
||||
l := len(namespace)
|
||||
|
||||
for _, key := range v.MapKeys() {
|
||||
|
||||
namespace = namespace[:l]
|
||||
|
||||
if s, valid = e.getMapKey(key, namespace); !valid {
|
||||
continue
|
||||
}
|
||||
|
||||
namespace = append(namespace, '[')
|
||||
namespace = append(namespace, s...)
|
||||
namespace = append(namespace, ']')
|
||||
|
||||
e.setFieldByType(v.MapIndex(key), namespace, -2, false)
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
|
||||
// if we get here then no custom time function declared so use RFC3339 by default
|
||||
if v.Type() == timeType {
|
||||
|
||||
if idx > -1 {
|
||||
namespace = append(namespace, '[')
|
||||
namespace = strconv.AppendInt(namespace, int64(idx), 10)
|
||||
namespace = append(namespace, ']')
|
||||
}
|
||||
|
||||
e.setVal(namespace, idx, v.Interface().(time.Time).Format(time.RFC3339))
|
||||
return
|
||||
}
|
||||
|
||||
if idx == -1 {
|
||||
e.traverseStruct(v, namespace, idx)
|
||||
return
|
||||
}
|
||||
|
||||
if idx > -1 {
|
||||
namespace = append(namespace, '[')
|
||||
namespace = strconv.AppendInt(namespace, int64(idx), 10)
|
||||
namespace = append(namespace, ']')
|
||||
}
|
||||
|
||||
e.traverseStruct(v, namespace, -2)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) getMapKey(key reflect.Value, namespace []byte) (string, bool) {
|
||||
|
||||
v, kind := ExtractType(key)
|
||||
|
||||
if e.e.customTypeFuncs != nil {
|
||||
|
||||
if cf, ok := e.e.customTypeFuncs[v.Type()]; ok {
|
||||
arr, err := cf(v.Interface())
|
||||
if err != nil {
|
||||
e.setError(namespace, err)
|
||||
return "", false
|
||||
}
|
||||
|
||||
return arr[0], true
|
||||
}
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return "", false
|
||||
|
||||
case reflect.String:
|
||||
return v.String(), true
|
||||
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return strconv.FormatUint(v.Uint(), 10), true
|
||||
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return strconv.FormatInt(v.Int(), 10), true
|
||||
|
||||
case reflect.Float32:
|
||||
return strconv.FormatFloat(v.Float(), 'f', -1, 32), true
|
||||
|
||||
case reflect.Float64:
|
||||
return strconv.FormatFloat(v.Float(), 'f', -1, 64), true
|
||||
|
||||
case reflect.Bool:
|
||||
return strconv.FormatBool(v.Bool()), true
|
||||
|
||||
default:
|
||||
e.setError(namespace, fmt.Errorf("Unsupported Map Key '%v' Namespace '%s'", v.String(), namespace))
|
||||
return "", false
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user