mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-01 15:00:00 +00:00
a156188b3e
* update dependencies, bump Go version to 1.19 * bump test image Go version * update golangci-lint * update gotosocial-drone-build * sign * linting, go fmt * update swagger docs * update swagger docs * whitespace * update contributing.md * fuckin whoopsie doopsie * linterino, linteroni * fix followrequest test not starting processor * fix other api/client tests not starting processor * fix remaining tests where processor not started * bump go-runners version * don't check last-webfingered-at, processor may have updated this * update swagger command * update bun to latest version * fix embed to work the same as before with new bun Signed-off-by: kim <grufwub@gmail.com> Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
136 lines
2.8 KiB
Go
136 lines
2.8 KiB
Go
package encoder
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
var (
|
|
Marshal func(interface{}) ([]byte, error)
|
|
Unmarshal func([]byte, interface{}) error
|
|
)
|
|
|
|
type FieldQuery struct {
|
|
Name string
|
|
Fields []*FieldQuery
|
|
hash string
|
|
}
|
|
|
|
func (q *FieldQuery) Hash() string {
|
|
if q.hash != "" {
|
|
return q.hash
|
|
}
|
|
b, _ := Marshal(q)
|
|
q.hash = string(b)
|
|
return q.hash
|
|
}
|
|
|
|
func (q *FieldQuery) MarshalJSON() ([]byte, error) {
|
|
if q.Name != "" {
|
|
if len(q.Fields) > 0 {
|
|
return Marshal(map[string][]*FieldQuery{q.Name: q.Fields})
|
|
}
|
|
return Marshal(q.Name)
|
|
}
|
|
return Marshal(q.Fields)
|
|
}
|
|
|
|
func (q *FieldQuery) QueryString() (FieldQueryString, error) {
|
|
b, err := Marshal(q)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return FieldQueryString(b), nil
|
|
}
|
|
|
|
type FieldQueryString string
|
|
|
|
func (s FieldQueryString) Build() (*FieldQuery, error) {
|
|
var query interface{}
|
|
if err := Unmarshal([]byte(s), &query); err != nil {
|
|
return nil, err
|
|
}
|
|
return s.build(reflect.ValueOf(query))
|
|
}
|
|
|
|
func (s FieldQueryString) build(v reflect.Value) (*FieldQuery, error) {
|
|
switch v.Type().Kind() {
|
|
case reflect.String:
|
|
return s.buildString(v)
|
|
case reflect.Map:
|
|
return s.buildMap(v)
|
|
case reflect.Slice:
|
|
return s.buildSlice(v)
|
|
case reflect.Interface:
|
|
return s.build(reflect.ValueOf(v.Interface()))
|
|
}
|
|
return nil, fmt.Errorf("failed to build field query")
|
|
}
|
|
|
|
func (s FieldQueryString) buildString(v reflect.Value) (*FieldQuery, error) {
|
|
b := []byte(v.String())
|
|
switch b[0] {
|
|
case '[', '{':
|
|
var query interface{}
|
|
if err := Unmarshal(b, &query); err != nil {
|
|
return nil, err
|
|
}
|
|
if str, ok := query.(string); ok {
|
|
return &FieldQuery{Name: str}, nil
|
|
}
|
|
return s.build(reflect.ValueOf(query))
|
|
}
|
|
return &FieldQuery{Name: string(b)}, nil
|
|
}
|
|
|
|
func (s FieldQueryString) buildSlice(v reflect.Value) (*FieldQuery, error) {
|
|
fields := make([]*FieldQuery, 0, v.Len())
|
|
for i := 0; i < v.Len(); i++ {
|
|
def, err := s.build(v.Index(i))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fields = append(fields, def)
|
|
}
|
|
return &FieldQuery{Fields: fields}, nil
|
|
}
|
|
|
|
func (s FieldQueryString) buildMap(v reflect.Value) (*FieldQuery, error) {
|
|
keys := v.MapKeys()
|
|
if len(keys) != 1 {
|
|
return nil, fmt.Errorf("failed to build field query object")
|
|
}
|
|
key := keys[0]
|
|
if key.Type().Kind() != reflect.String {
|
|
return nil, fmt.Errorf("failed to build field query. invalid object key type")
|
|
}
|
|
name := key.String()
|
|
def, err := s.build(v.MapIndex(key))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &FieldQuery{
|
|
Name: name,
|
|
Fields: def.Fields,
|
|
}, nil
|
|
}
|
|
|
|
type queryKey struct{}
|
|
|
|
func FieldQueryFromContext(ctx context.Context) *FieldQuery {
|
|
query := ctx.Value(queryKey{})
|
|
if query == nil {
|
|
return nil
|
|
}
|
|
q, ok := query.(*FieldQuery)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return q
|
|
}
|
|
|
|
func SetFieldQueryToContext(ctx context.Context, query *FieldQuery) context.Context {
|
|
return context.WithValue(ctx, queryKey{}, query)
|
|
}
|