func valueForAssertions(v reflect.Value) reflect.Value {
	v = unwrapPointer(v)
	if !v.IsValid() || v.Kind() == reflect.Interface || !v.CanAddr() {
		return v
	}
	return v.Addr()
}
valueForAssertions returns the value's innermost pointer or v itself
if v does not represent a pointer.
package graphql
import (
	"context"
	"encoding"
	"encoding/json"
	"fmt"
	"reflect"
	"sort"
	"strconv"
	"strings"
	"unicode/utf16"
	"golang.org/x/xerrors"
	"zombiezen.com/go/graphql-server/internal/gqlang"
)
type Value struct {
	typ *gqlType
	val interface{}  
}
type Field struct {
	Key string
	Value Value
}
func (f Field) encodeGraphQL(sb *strings.Builder, indent int) {
	sb.WriteString(f.Key)
	sb.WriteString(": ")
	f.Value.encodeGraphQL(sb, indent)
}
type FieldResolver interface {
	ResolveField(ctx context.Context, req FieldRequest) (interface{}, error)
}
type FieldRequest struct {
	Name      string
	Args      map[string]Value
	Selection *SelectionSet
}
func (schema *Schema) valueFromGo(ctx context.Context, variables map[string]Value, goValue reflect.Value, typ *gqlType, sel *SelectionSet) (Value, []error) {
	goValue = unwrapPointer(goValue)
	if !goValue.IsValid() {
		if !typ.isNullable() {
			return Value{typ: typ}, []error{xerrors.Errorf("cannot convert nil to %v", typ)}
		}
		return Value{typ: typ, val: nil}, nil
	}
	resolvedType, err := resolveDynamicType(schema.types, goValue, typ)
	if err != nil {
		return Value{typ: typ}, []error{err}
	}
	typ = resolvedType
	sel = sel.forType(typ.toNullable().Name().String())
	if isGraphQLNull(interfaceValueForAssertions(goValue)) {
		if !typ.isNullable() {
			return Value{typ: typ}, []error{xerrors.Errorf("cannot convert nil to %v", typ)}
		}
		return Value{typ: typ, val: nil}, nil
	}
	switch {
	case typ.isScalar() || typ.isEnum():
		v, err := scalarFromGo(goValue, typ)
		if err != nil {
			return Value{typ: typ}, []error{err}
		}
		return v, nil
	case typ.isList():
		if kind := goValue.Kind(); kind != reflect.Slice && kind != reflect.Array {
			return Value{typ: typ}, []error{xerrors.Errorf("cannot convert %v to %v", goValue.Type(), typ)}
		}
		gqlValues := make([]Value, goValue.Len())
		var errs []error
		for i := range gqlValues {
			var ierrs []error
			gqlValues[i], ierrs = schema.valueFromGo(ctx, variables, goValue.Index(i), typ.listElem, sel)
			for _, err := range ierrs {
				errs = append(errs, &listElementError{idx: i, err: err})
			}
			if len(errs) > 0 && !typ.listElem.isNullable() {
				return Value{typ: typ}, errs
			}
		}
		return Value{typ: typ, val: gqlValues}, errs
	case typ.isObject():
		if sel == nil {
			return Value{typ: typ, val: []Field(nil)}, nil
		}
		gqlFields := make([]Field, 0, len(sel.fields))
		goValue = valueForAssertions(goValue)
		desc := schema.typeDescriptor(typeKey{
			goType:  goValue.Type(),
			gqlType: typ.obj,
		})
		if desc.err != nil {
			return Value{typ: typ}, []error{desc.err}
		}
		var errs []error
		for _, f := range sel.fields {
			var fval Value
			var ferrs []error
			switch f.name {
			case typeNameFieldName:
				fval = Value{
					typ: stringType.toNonNullable(),
					val: typ.toNullable().String(),
				}
			case schemaFieldName:
				fval, ferrs = schema.introspectSchema(ctx, variables, f)
			case typeByNameFieldName:
				fval, ferrs = schema.introspectType(ctx, variables, f)
			default:
				fval, ferrs = schema.readField(ctx, variables, goValue, desc, typ.obj.field(f.name).typ, f)
			}
			gqlFields = append(gqlFields, Field{Key: f.key, Value: fval})
			errs = append(errs, ferrs...)
		}
		return Value{typ: typ, val: gqlFields}, errs
	default:
		return Value{typ: typ}, []error{xerrors.Errorf("unhandled type: %v", typ)}
	}
}
type Typer interface {
	GraphQLType() string
}
func resolveDynamicType(types map[string]*gqlType, goValue reflect.Value, typ *gqlType) (*gqlType, error) {
	if typer, ok := interfaceValueForAssertions(goValue).(Typer); ok {
		dynTypeName := typer.GraphQLType()
		dynType := types[dynTypeName].toNullable()
		if dynType == nil {
			return typ, xerrors.Errorf("Go value of type %v has unknown dynamic type %q", goValue.Type(), dynTypeName)
		}
		if _, permitted := typ.possibleTypes()[dynType]; !permitted {
			return typ, xerrors.Errorf("GraphQL type %v not permitted as %v", dynType, typ)
		}
		if dynType != typ.toNullable() {
			if !typ.isNullable() {
				return dynType.toNonNullable(), nil
			}
			return dynType, nil
		}
		return typ, nil
	}
	if !typ.isAbstract() {
		return typ, nil
	}
	goType := goValue.Type()
	for goType.Name() == "" && goType.Kind() == reflect.Ptr {
		goType = goType.Elem()
	}
	dynType := findTypeCaseInsensitive(types, goType.Name())
	if dynType == nil {
		return typ, xerrors.Errorf("%v has no known GraphQL type but used as %v (missing a GraphQLType method?)", goValue.Type(), typ)
	}
	if _, permitted := typ.possibleTypes()[dynType]; !permitted {
		return typ, xerrors.Errorf("GraphQL type %v not permitted as %v", dynType, typ)
	}
	if !typ.isNullable() {
		return dynType.toNonNullable(), nil
	}
	return dynType, nil
}
func findTypeCaseInsensitive(types map[string]*gqlType, name string) *gqlType {
	lower := strings.ToLower(name)
	for n, t := range types {
		if lower == strings.ToLower(n) {
			return t
		}
	}
	return nil
}
func coerceArgumentValues(s *selectionSetScope, argDefns inputValueDefinitionList, args *gqlang.Arguments) (map[string]Value, []error) {
	argValues := make(map[string]Value)
	var errs []error
	for _, defn := range argDefns {
		arg := args.ByName(defn.name)
		if arg == nil {
			argValues[defn.name] = defn.defaultValue
			continue
		}
		if arg.Value.VariableRef != nil {
			if _, hasValue := s.variables[arg.Value.VariableRef.Name.Value]; !hasValue {
				argValues[defn.name] = defn.defaultValue
				continue
			}
		}
		var argErrs []error
		argValues[defn.name], argErrs = coerceInputValue(s, defn.Type(), arg.Value)
		for _, err := range argErrs {
			errs = append(errs, xerrors.Errorf("argument %s: %w", defn.name, err))
		}
	}
	return argValues, errs
}
func coerceConstantInputValue(typ *gqlType, inputValue *gqlang.InputValue) Value {
	v, errs := coerceInputValue(nil, typ, inputValue)
	if len(errs) > 0 {
		panic(errs[0])
	}
	return v
}
func coerceInputValue(s *selectionSetScope, typ *gqlType, inputValue *gqlang.InputValue) (Value, []error) {
	switch {
	case inputValue.Null != nil:
		return Value{typ: typ}, nil
	case inputValue.VariableRef != nil:
		name := inputValue.VariableRef.Name.Value
		v := s.variables[name]
		if v.IsNull() && !typ.isNullable() {
			return Value{typ: typ}, []error{&ResponseError{
				Message: fmt.Sprintf("cannot use null variable $%s as %v", name, typ),
				Locations: []Location{
					astPositionToLocation(inputValue.VariableRef.Dollar.ToPosition(s.source)),
				},
			}}
		}
		return Value{
			typ: typ,
			val: v.val,
		}, nil
	case typ.isScalar() || typ.isEnum():
		return Value{
			typ: typ,
			val: inputValue.Scalar.Value(),
		}, nil
	case typ.isList():
		if inputValue.List == nil {
			value, errs := coerceInputValue(s, typ.listElem, inputValue)
			if len(errs) > 0 {
				return Value{typ: typ}, errs
			}
			return Value{
				typ: typ,
				val: []Value{value},
			}, nil
		}
		val := make([]Value, 0, len(inputValue.List.Values))
		var errs []error
		for i, elem := range inputValue.List.Values {
			elemValue, elemErrs := coerceInputValue(s, typ.listElem, elem)
			val = append(val, elemValue)
			for _, err := range elemErrs {
				errs = append(errs, xerrors.Errorf("list[%d]: %w", i, err))
			}
		}
		return Value{typ: typ, val: val}, errs
	case typ.isInputObject():
		val := make(map[string]Value)
		var errs []error
		for _, field := range inputValue.InputObject.Fields {
			fieldName := field.Name.Value
			fieldType := typ.input.fields.byName(fieldName).Type()
			var fieldErrs []error
			val[fieldName], fieldErrs = coerceInputValue(s, fieldType, field.Value)
			for _, err := range fieldErrs {
				errs = append(errs, xerrors.Errorf("input field %s: %w", fieldName, err))
			}
		}
		return Value{typ: typ, val: val}, errs
	default:
		panic("unhandled input type")
	}
}
func (schema *Schema) readField(ctx context.Context, variables map[string]Value, goValue reflect.Value, desc *typeDescriptor, typ *gqlType, f *SelectedField) (Value, []error) {
	result, err := desc.read(ctx, valueForAssertions(goValue), f.toRequest())
	if err != nil {
		return Value{typ: typ}, []error{wrapFieldError(f.key, f.loc, err)}
	}
	v, errs := schema.valueFromGo(ctx, variables, result, typ, f.sub)
	if len(errs) > 0 {
		for i := range errs {
			errs[i] = wrapFieldError(f.key, f.loc, errs[i])
		}
		return v, errs
	}
	return v, nil
}
func scalarFromGo(goValue reflect.Value, typ *gqlType) (Value, error) {
	goValue = unwrapPointer(goValue)
	goIface := interfaceValueForAssertions(goValue)
	if !goValue.IsValid() || isGraphQLNull(goIface) {
		if !typ.isNullable() {
			return Value{}, xerrors.Errorf("cannot convert nil to %v", typ)
		}
		return Value{typ: typ, val: nil}, nil
	}
	if marshaler, ok := goIface.(encoding.TextMarshaler); ok {
		b, err := marshaler.MarshalText()
		if err != nil {
			return Value{}, err
		}
		val := string(b)
		if typ.isEnum() && !typ.enum.has(val) {
			return Value{typ: typ}, xerrors.Errorf("%q is not a valid value for %v", val, typ)
		}
		return Value{typ: typ, val: val}, nil
	}
	switch typ.toNullable() {
	case booleanType:
		if goValue.Kind() != reflect.Bool {
			return Value{}, xerrors.Errorf("cannot convert %v to %v", goValue.Type(), typ)
		}
		return Value{typ: typ, val: strconv.FormatBool(goValue.Bool())}, nil
	case intType:
		if goValue.Kind() != reflect.Int32 && goValue.Kind() != reflect.Int {
			return Value{}, xerrors.Errorf("cannot convert %v to %v", goValue.Type(), typ)
		}
		i := goValue.Int()
		const maxInt32 = 1 << 31
		const minInt32 = -maxInt32 - 1
		if i < minInt32 || maxInt32 < i {
			return Value{}, xerrors.New("integer out of GraphQL range")
		}
		return Value{typ: typ, val: strconv.FormatInt(i, 10)}, nil
	case floatType:
		var bitSize int
		switch goValue.Kind() {
		case reflect.Float32:
			bitSize = 32
		case reflect.Float64:
			bitSize = 64
		default:
			return Value{}, xerrors.Errorf("cannot convert %v to %v", goValue.Type(), typ)
		}
		val := strconv.FormatFloat(goValue.Float(), 'g', -1, bitSize)
		return Value{typ: typ, val: val}, nil
	case idType:
		if k := goValue.Kind(); k == reflect.Int32 || k == reflect.Int || k == reflect.Int64 {
			return Value{typ: typ, val: strconv.FormatInt(goValue.Int(), 10)}, nil
		}
		fallthrough
	default:
		if goValue.Kind() != reflect.String {
			return Value{typ: typ}, xerrors.Errorf("cannot convert %v to %v", goValue.Type(), typ)
		}
		val := goValue.String()
		if typ.isEnum() && !typ.enum.has(val) {
			return Value{typ: typ}, xerrors.Errorf("%q is not a valid value for %v", val, typ)
		}
		return Value{typ: typ, val: val}, nil
	}
}
func unwrapPointer(v reflect.Value) reflect.Value {
	for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
		if v.IsNil() {
			return reflect.Value{}
		}
		v = v.Elem()
	}
	return v
}