func (q *qtNode) markXmitted() {
	q.xmitted = true
}
markXmitted marks the node as transmitted.
package client
import (
	"github.com/rgraphql/magellan/types"
	"github.com/rgraphql/magellan/types/gqlast"
	"github.com/rgraphql/magellan/varstore"
	"github.com/graphql-go/graphql/language/ast"
	proto "github.com/rgraphql/rgraphql"
)
type schemaLookup func(ast.Type) ast.TypeDefinition
type qtNode struct {
	id uint32
	name string
	objDef *ast.ObjectDefinition
	children []*qtNode
	args argsMap
	parent *qtNode
	varStore *varstore.VariableStore
	refCount uint32
	gcNext bool
	xmitted bool
}
func newQtNode(objDef *ast.ObjectDefinition, varStore *varstore.VariableStore) *qtNode {
	return &qtNode{name: objDef.Name.Value, objDef: objDef, varStore: varStore}
}
func (q *qtNode) buildProto() *proto.RGQLQueryTreeNode {
	children := make([]*proto.RGQLQueryTreeNode, len(q.children))
	for i := range q.children {
		children[i] = q.children[i].buildProto()
	}
	return &proto.RGQLQueryTreeNode{
		Id:        q.id,
		FieldName: q.name,
		Args:      q.args.BuildProto(),
		Children:  children,
	}
}
func (q *qtNode) flagGcNext() {
	q.gcNext = true
	if q.parent != nil {
		q.parent.flagGcNext()
	}
}
func (q *qtNode) matchesField(f *ast.Field, args argsMap) bool {
	fieldName := f.Name.Value
	if fieldName != q.name {
		return false
	}
	return q.args.Equals(args)
}
func (q *qtNode) lookupChildByID(qnID uint32) *qtNode {
	for _, child := range q.children {
		if child.id == qnID {
			return child
		}
	}
	return nil
}
func (q *qtNode) resolveChild(field *ast.Field, lookupType schemaLookup, allocNode func() *qtNode) (*qtNode, error) {
	fieldName := field.Name.Value
	childFieldDef := q.findSchemaField(fieldName)
	if childFieldDef == nil {
		return nil, fieldNotFoundErr(fieldName, q.name)
	}
	var atdObj *ast.ObjectDefinition
	childFieldType := childFieldDef.Type
	childFieldTypeUnderlying := gqlast.UnwrapASTType(childFieldType)
	if !types.IsAstPrimitive(childFieldTypeUnderlying) {
		atd := lookupType(childFieldTypeUnderlying)
		if atd != nil {
			var atdOk bool
			atdObj, atdOk = atd.(*ast.ObjectDefinition)
			if !atdOk {
				atdObj = nil
			}
		}
		if atdObj == nil {
			ctName, ctOk := childFieldTypeUnderlying.(*ast.Named)
			if ctOk {
				return nil, typeNotFoundErr(ctName.Name.Value)
			}
			return nil, typeNotFoundErr("[unknown reference type]")
		}
	}
	argsm, err := newArgsMapFromAst(q.varStore, field.Arguments)
	if err != nil {
		return nil, err
	}
	for _, child := range q.children {
		if child.matchesField(field, argsm) {
			return child, nil
		}
	}
	childNod := allocNode()
	childNod.varStore = q.varStore
	childNod.args = argsm
	childNod.name = fieldName
	childNod.objDef = atdObj
	childNod.parent = q
	q.children = append(q.children, childNod)
	return childNod, nil
}
func (q *qtNode) findSchemaField(fieldName string) *ast.FieldDefinition {
	if q.objDef == nil {
		return nil
	}
	for _, f := range q.objDef.Fields {
		if f.Name == nil {
			continue
		}
		if fieldName == f.Name.Value {
			return f
		}
	}
	return nil
}
func (q *qtNode) gcSweep(purgeNodesCb func([]*qtNode)) bool {
	var unrefChildren []*qtNode
	if q.gcNext {
		q.gcNext = false
		for i := 0; i < len(q.children); i++ {
			child := q.children[i]
			if !child.gcSweep(purgeNodesCb) {
				q.children[i] = q.children[len(q.children)-1]
				q.children[len(q.children)-1] = nil
				q.children = q.children[:len(q.children)-1]
				if child.xmitted {
					unrefChildren = append(unrefChildren, child)
				}
				i--
			}
		}
	}
	qReferenced := q.refCount != 0 || q.parent == nil
	if len(unrefChildren) != 0 && qReferenced {
		purgeNodesCb(unrefChildren)
	}
	return qReferenced
}