summaryrefslogtreecommitdiff
path: root/vendor/github.com/go-playground/form/v4/cache.go
diff options
context:
space:
mode:
authorLibravatar zowhoey <11893985+zowhoey@users.noreply.github.com>2023-03-06 09:30:19 +0000
committerLibravatar GitHub <noreply@github.com>2023-03-06 10:30:19 +0100
commitf518f649f800e52d32fe53580c528ffa042f7154 (patch)
treec14bb8b513008d1c1e7bab0908cfc99fe18f1507 /vendor/github.com/go-playground/form/v4/cache.go
parent[chore]: Bump github.com/jackc/pgx/v4 from 4.17.2 to 4.18.1 (#1595) (diff)
downloadgotosocial-f518f649f800e52d32fe53580c528ffa042f7154.tar.xz
[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>
Diffstat (limited to 'vendor/github.com/go-playground/form/v4/cache.go')
-rw-r--r--vendor/github.com/go-playground/form/v4/cache.go133
1 files changed, 133 insertions, 0 deletions
diff --git a/vendor/github.com/go-playground/form/v4/cache.go b/vendor/github.com/go-playground/form/v4/cache.go
new file mode 100644
index 000000000..47e5fce96
--- /dev/null
+++ b/vendor/github.com/go-playground/form/v4/cache.go
@@ -0,0 +1,133 @@
+package form
+
+import (
+ "reflect"
+ "sort"
+ "strings"
+ "sync"
+ "sync/atomic"
+)
+
+type cacheFields []cachedField
+
+func (s cacheFields) Len() int {
+ return len(s)
+}
+
+func (s cacheFields) Less(i, j int) bool {
+ return !s[i].isAnonymous
+}
+
+func (s cacheFields) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+type cachedField struct {
+ idx int
+ name string
+ isAnonymous bool
+ isOmitEmpty bool
+}
+
+type cachedStruct struct {
+ fields cacheFields
+}
+
+type structCacheMap struct {
+ m atomic.Value // map[reflect.Type]*cachedStruct
+ lock sync.Mutex
+ tagFn TagNameFunc
+}
+
+// TagNameFunc allows for adding of a custom tag name parser
+type TagNameFunc func(field reflect.StructField) string
+
+func newStructCacheMap() *structCacheMap {
+
+ sc := new(structCacheMap)
+ sc.m.Store(make(map[reflect.Type]*cachedStruct))
+
+ return sc
+}
+
+func (s *structCacheMap) Get(key reflect.Type) (value *cachedStruct, ok bool) {
+ value, ok = s.m.Load().(map[reflect.Type]*cachedStruct)[key]
+ return
+}
+
+func (s *structCacheMap) Set(key reflect.Type, value *cachedStruct) {
+
+ m := s.m.Load().(map[reflect.Type]*cachedStruct)
+
+ nm := make(map[reflect.Type]*cachedStruct, len(m)+1)
+ for k, v := range m {
+ nm[k] = v
+ }
+ nm[key] = value
+ s.m.Store(nm)
+}
+
+func (s *structCacheMap) parseStruct(mode Mode, current reflect.Value, key reflect.Type, tagName string) *cachedStruct {
+
+ s.lock.Lock()
+
+ // could have been multiple trying to access, but once first is done this ensures struct
+ // isn't parsed again.
+ cs, ok := s.Get(key)
+ if ok {
+ s.lock.Unlock()
+ return cs
+ }
+
+ typ := current.Type()
+ cs = &cachedStruct{fields: make([]cachedField, 0, 4)} // init 4, betting most structs decoding into have at aleast 4 fields.
+
+ numFields := current.NumField()
+
+ var fld reflect.StructField
+ var name string
+ var idx int
+ var isOmitEmpty bool
+
+ for i := 0; i < numFields; i++ {
+ isOmitEmpty = false
+ fld = typ.Field(i)
+
+ if fld.PkgPath != blank && !fld.Anonymous {
+ continue
+ }
+
+ if s.tagFn != nil {
+ name = s.tagFn(fld)
+ } else {
+ name = fld.Tag.Get(tagName)
+ }
+
+ if name == ignore {
+ continue
+ }
+
+ if mode == ModeExplicit && len(name) == 0 {
+ continue
+ }
+
+ // check for omitempty
+ if idx = strings.LastIndexByte(name, ','); idx != -1 {
+ isOmitEmpty = name[idx+1:] == "omitempty"
+ name = name[:idx]
+ }
+
+ if len(name) == 0 {
+ name = fld.Name
+ }
+
+ cs.fields = append(cs.fields, cachedField{idx: i, name: name, isAnonymous: fld.Anonymous, isOmitEmpty: isOmitEmpty})
+ }
+
+ sort.Sort(cs.fields)
+ s.Set(typ, cs)
+
+ s.lock.Unlock()
+
+ return cs
+}