Skip to content

Commit

Permalink
moved packer into separate package
Browse files Browse the repository at this point in the history
  • Loading branch information
neelance committed Jun 11, 2017
1 parent 073edcc commit c76ff4d
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package resolvable
package packer

import (
"fmt"
Expand All @@ -15,7 +15,51 @@ type packer interface {
Pack(value interface{}) (reflect.Value, error)
}

func (b *execBuilder) assignPacker(target *packer, schemaType common.Type, reflectType reflect.Type) error {
type Builder struct {
packerMap map[typePair]*packerMapEntry
structPackers []*StructPacker
}

type typePair struct {
graphQLType common.Type
resolverType reflect.Type
}

type packerMapEntry struct {
packer packer
targets []*packer
}

func NewBuilder() *Builder {
return &Builder{
packerMap: make(map[typePair]*packerMapEntry),
}
}

func (b *Builder) Finish() error {
for _, entry := range b.packerMap {
for _, target := range entry.targets {
*target = entry.packer
}
}

for _, p := range b.structPackers {
p.defaultStruct = reflect.New(p.structType).Elem()
for _, f := range p.fields {
if defaultVal := f.field.Default; defaultVal != nil {
v, err := f.fieldPacker.Pack(defaultVal.Value(nil))
if err != nil {
return err
}
p.defaultStruct.FieldByIndex(f.fieldIndex).Set(v)
}
}
}

return nil
}

func (b *Builder) assignPacker(target *packer, schemaType common.Type, reflectType reflect.Type) error {
k := typePair{schemaType, reflectType}
ref, ok := b.packerMap[k]
if !ok {
Expand All @@ -31,7 +75,7 @@ func (b *execBuilder) assignPacker(target *packer, schemaType common.Type, refle
return nil
}

func (b *execBuilder) makePacker(schemaType common.Type, reflectType reflect.Type) (packer, error) {
func (b *Builder) makePacker(schemaType common.Type, reflectType reflect.Type) (packer, error) {
t, nonNull := unwrapNonNull(schemaType)
if !nonNull {
if reflectType.Kind() != reflect.Ptr {
Expand All @@ -57,7 +101,7 @@ func (b *execBuilder) makePacker(schemaType common.Type, reflectType reflect.Typ
return b.makeNonNullPacker(t, reflectType)
}

func (b *execBuilder) makeNonNullPacker(schemaType common.Type, reflectType reflect.Type) (packer, error) {
func (b *Builder) makeNonNullPacker(schemaType common.Type, reflectType reflect.Type) (packer, error) {
if u, ok := reflect.New(reflectType).Interface().(Unmarshaler); ok {
if !u.ImplementsGraphQLType(schemaType.String()) {
return nil, fmt.Errorf("can not unmarshal %s into %s", schemaType, reflectType)
Expand All @@ -83,7 +127,7 @@ func (b *execBuilder) makeNonNullPacker(schemaType common.Type, reflectType refl
}, nil

case *schema.InputObject:
e, err := b.makeStructPacker(t.Values, reflectType)
e, err := b.MakeStructPacker(t.Values, reflectType)
if err != nil {
return nil, err
}
Expand All @@ -109,7 +153,7 @@ func (b *execBuilder) makeNonNullPacker(schemaType common.Type, reflectType refl
}
}

func (b *execBuilder) makeStructPacker(values common.InputValueList, typ reflect.Type) (*StructPacker, error) {
func (b *Builder) MakeStructPacker(values common.InputValueList, typ reflect.Type) (*StructPacker, error) {
structType := typ
usePtr := false
if typ.Kind() == reflect.Ptr {
Expand Down Expand Up @@ -310,3 +354,14 @@ func unmarshalInput(typ reflect.Type, input interface{}) (interface{}, error) {

return nil, fmt.Errorf("incompatible type")
}

func unwrapNonNull(t common.Type) (common.Type, bool) {
if nn, ok := t.(*common.NonNull); ok {
return nn.OfType, true
}
return t, false
}

func stripUnderscore(s string) string {
return strings.Replace(s, "_", "", -1)
}
44 changes: 10 additions & 34 deletions internal/exec/resolvable/resolvable.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"

"github.com/neelance/graphql-go/internal/common"
"github.com/neelance/graphql-go/internal/exec/packer"
"github.com/neelance/graphql-go/internal/schema"
)

Expand All @@ -32,7 +33,7 @@ type Field struct {
TypeName string
MethodIndex int
HasContext bool
ArgsPacker *StructPacker
ArgsPacker *packer.StructPacker
HasError bool
ValueExec Resolvable
TraceLabel string
Expand Down Expand Up @@ -85,8 +86,7 @@ func ApplyResolver(s *schema.Schema, resolver interface{}) (*Schema, error) {
type execBuilder struct {
schema *schema.Schema
resMap map[typePair]*resMapEntry
packerMap map[typePair]*packerMapEntry
structPackers []*StructPacker
packerBuilder *packer.Builder
}

type typePair struct {
Expand All @@ -99,16 +99,11 @@ type resMapEntry struct {
targets []*Resolvable
}

type packerMapEntry struct {
packer packer
targets []*packer
}

func newBuilder(s *schema.Schema) *execBuilder {
return &execBuilder{
schema: s,
resMap: make(map[typePair]*resMapEntry),
packerMap: make(map[typePair]*packerMapEntry),
schema: s,
resMap: make(map[typePair]*resMapEntry),
packerBuilder: packer.NewBuilder(),
}
}

Expand All @@ -119,26 +114,7 @@ func (b *execBuilder) finish() error {
}
}

for _, entry := range b.packerMap {
for _, target := range entry.targets {
*target = entry.packer
}
}

for _, p := range b.structPackers {
p.defaultStruct = reflect.New(p.structType).Elem()
for _, f := range p.fields {
if defaultVal := f.field.Default; defaultVal != nil {
v, err := f.fieldPacker.Pack(defaultVal.Value(nil))
if err != nil {
return err
}
p.defaultStruct.FieldByIndex(f.fieldIndex).Set(v)
}
}
}

return nil
return b.packerBuilder.Finish()
}

func (b *execBuilder) assignExec(target *Resolvable, t common.Type, resolverType reflect.Type) error {
Expand Down Expand Up @@ -212,7 +188,7 @@ func makeScalarExec(t *schema.Scalar, resolverType reflect.Type) (Resolvable, er
implementsType = (t.Name == "String")
case *bool:
implementsType = (t.Name == "Boolean")
case Unmarshaler:
case packer.Unmarshaler:
implementsType = r.ImplementsGraphQLType(t.Name)
}
if !implementsType {
Expand Down Expand Up @@ -291,13 +267,13 @@ func (b *execBuilder) makeFieldExec(typeName string, f *schema.Field, m reflect.
in = in[1:]
}

var argsPacker *StructPacker
var argsPacker *packer.StructPacker
if len(f.Args) > 0 {
if len(in) == 0 {
return nil, fmt.Errorf("must have parameter for field arguments")
}
var err error
argsPacker, err = b.makeStructPacker(f.Args, in[0])
argsPacker, err = b.packerBuilder.MakeStructPacker(f.Args, in[0])
if err != nil {
return nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions internal/exec/selected/selected.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/neelance/graphql-go/errors"
"github.com/neelance/graphql-go/internal/common"
"github.com/neelance/graphql-go/internal/exec/packer"
"github.com/neelance/graphql-go/internal/exec/resolvable"
"github.com/neelance/graphql-go/internal/query"
"github.com/neelance/graphql-go/internal/schema"
Expand Down Expand Up @@ -92,7 +93,7 @@ func applySelectionSet(r *Request, e *resolvable.Object, sels []query.Selection)
})

case "__type":
p := resolvable.ValuePacker{ValueType: reflect.TypeOf("")}
p := packer.ValuePacker{ValueType: reflect.TypeOf("")}
v, err := p.Pack(field.Arguments.MustGet("name").Value(r.Vars))
if err != nil {
r.AddError(errors.Errorf("%s", err))
Expand Down Expand Up @@ -192,7 +193,7 @@ func applyField(r *Request, e resolvable.Resolvable, sels []query.Selection) []S

func skipByDirective(r *Request, directives common.DirectiveList) bool {
if d := directives.Get("skip"); d != nil {
p := resolvable.ValuePacker{ValueType: reflect.TypeOf(false)}
p := packer.ValuePacker{ValueType: reflect.TypeOf(false)}
v, err := p.Pack(d.Args.MustGet("if").Value(r.Vars))
if err != nil {
r.AddError(errors.Errorf("%s", err))
Expand All @@ -203,7 +204,7 @@ func skipByDirective(r *Request, directives common.DirectiveList) bool {
}

if d := directives.Get("include"); d != nil {
p := resolvable.ValuePacker{ValueType: reflect.TypeOf(false)}
p := packer.ValuePacker{ValueType: reflect.TypeOf(false)}
v, err := p.Pack(d.Args.MustGet("if").Value(r.Vars))
if err != nil {
r.AddError(errors.Errorf("%s", err))
Expand Down

0 comments on commit c76ff4d

Please sign in to comment.