mirror of
https://github.com/oarkflow/mq.git
synced 2025-10-06 08:26:52 +08:00
121 lines
2.2 KiB
Go
121 lines
2.2 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
type form struct {
|
|
dest map[string]any
|
|
raw string
|
|
pathCache map[string]int
|
|
}
|
|
|
|
func newForm(raw string) *form {
|
|
f := new(form)
|
|
f.raw = raw
|
|
f.pathCache = make(map[string]int)
|
|
return f
|
|
}
|
|
|
|
func (f *form) reset() {
|
|
f.dest = make(map[string]any)
|
|
}
|
|
|
|
func (f *form) decode() (map[string]any, error) {
|
|
f.reset()
|
|
vals := make(map[string]any)
|
|
for _, v := range strings.Split(f.raw, "&") {
|
|
if v == "" {
|
|
continue
|
|
}
|
|
index := strings.Index(v, "=")
|
|
if index > 0 {
|
|
key := v[:index]
|
|
val := v[index+1:]
|
|
|
|
f.insertValue(&vals, key, val)
|
|
} else {
|
|
f.insertValue(&vals, v, "")
|
|
}
|
|
}
|
|
return f.parseArray(vals), nil
|
|
}
|
|
|
|
func (f *form) insertValue(destP *map[string]any, key string, val string) {
|
|
key, _ = url.PathUnescape(key)
|
|
var path []string
|
|
if strings.Contains(key, "[") || strings.Contains(key, "]") {
|
|
var current string
|
|
for _, c := range key {
|
|
switch c {
|
|
case '[':
|
|
if len(current) > 0 {
|
|
path = append(path, current)
|
|
current = ""
|
|
}
|
|
case ']':
|
|
path = append(path, current)
|
|
current = ""
|
|
continue
|
|
default:
|
|
current += string(c)
|
|
}
|
|
}
|
|
if len(current) > 0 {
|
|
path = append(path, current)
|
|
}
|
|
} else {
|
|
path = append(path, key)
|
|
}
|
|
dest := *destP
|
|
for i, k := range path {
|
|
if i == len(path)-1 {
|
|
break
|
|
}
|
|
if k == "" {
|
|
c := strings.Join(path, ",")
|
|
k = fmt.Sprint(f.pathCache[c])
|
|
f.pathCache[c] = f.pathCache[c] + 1
|
|
}
|
|
if _, ok := dest[k].(map[string]any); !ok {
|
|
dest[k] = make(map[string]any)
|
|
}
|
|
dest = dest[k].(map[string]any)
|
|
}
|
|
p := path[len(path)-1]
|
|
if p == "" {
|
|
p = fmt.Sprint(len(dest))
|
|
}
|
|
val, _ = url.QueryUnescape(val)
|
|
dest[p] = val
|
|
}
|
|
|
|
func (f *form) parseArrayItem(dest map[string]any) any {
|
|
var arr []any
|
|
for i := 0; i < len(dest); i++ {
|
|
item, ok := dest[fmt.Sprint(i)]
|
|
if !ok {
|
|
return dest
|
|
}
|
|
arr = append(arr, item)
|
|
}
|
|
return arr
|
|
}
|
|
|
|
func (f *form) parseArray(dest map[string]any) map[string]any {
|
|
for k, v := range dest {
|
|
mv, ok := v.(map[string]any)
|
|
if ok {
|
|
f.parseArray(mv)
|
|
dest[k] = f.parseArrayItem(mv)
|
|
}
|
|
}
|
|
return dest
|
|
}
|
|
|
|
func DecodeForm(src []byte) (map[string]any, error) {
|
|
return newForm(FromByte(src)).decode()
|
|
}
|