123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- 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)
- }
|