...
1 package graphql
2
3 import (
4 "context"
5 "errors"
6 "reflect"
7 )
8
9 const unmarshalInputCtx key = "unmarshal_input_context"
10
11
12
13 func BuildUnmarshalerMap(unmarshaler ...interface{}) map[reflect.Type]reflect.Value {
14 maps := make(map[reflect.Type]reflect.Value)
15 for _, v := range unmarshaler {
16 ft := reflect.TypeOf(v)
17 if ft.Kind() == reflect.Func {
18 maps[ft.Out(0)] = reflect.ValueOf(v)
19 }
20 }
21
22 return maps
23 }
24
25
26 func WithUnmarshalerMap(ctx context.Context, maps map[reflect.Type]reflect.Value) context.Context {
27 return context.WithValue(ctx, unmarshalInputCtx, maps)
28 }
29
30
31 func UnmarshalInputFromContext(ctx context.Context, raw, v interface{}) error {
32 m, ok := ctx.Value(unmarshalInputCtx).(map[reflect.Type]reflect.Value)
33 if m == nil || !ok {
34 return errors.New("graphql: the input context is empty")
35 }
36
37 rv := reflect.ValueOf(v)
38 if rv.Kind() != reflect.Ptr || rv.IsNil() {
39 return errors.New("graphql: input must be a non-nil pointer")
40 }
41 if fn, ok := m[rv.Elem().Type()]; ok {
42 res := fn.Call([]reflect.Value{
43 reflect.ValueOf(ctx),
44 reflect.ValueOf(raw),
45 })
46 if err := res[1].Interface(); err != nil {
47 return err.(error)
48 }
49
50 rv.Elem().Set(res[0])
51 return nil
52 }
53
54 return errors.New("graphql: no unmarshal function found")
55 }
56
View as plain text