Example #1
0
/**
 * Given a type and any value, return a runtime value coerced to match the type.
 */
func coerceValue(typ typs.QLType, value interface{}) interface{} {
	if typ, ok := typ.(*typs.QLNonNull); ok {
		nullableType := typ.OfType
		return coerceValue(nullableType, value)
	}

	v := reflect.ValueOf(value)
	if value == nil || v.IsNil() {
		return nil
	}

	switch typ := typ.(type) {
	case *typs.QLList:
		itemType := typ.OfType
		if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
			result := make([]interface{}, v.Len())[:0]
			for i, n := 0, v.Len(); i < n; i++ {
				fieldValue := v.Field(i)
				result = append(result, coerceValue(itemType, fieldValue))
			}
			return result
		}
		return []interface{}{coerceValue(itemType, value)}

	case *typs.QLInputObject:
		fields := typ.GetFields()
		obj := make(map[string]interface{})
		for fieldName, field := range fields {
			runtimeField := v.FieldByName(fieldName)
			if !runtimeField.IsValid() {
				continue
			}

			fieldValue := coerceValue(field.Type, runtimeField.Interface())
			if fieldValue == nil {
				fieldValue = field.DefaultValue
			}
			if fieldValue != nil {
				obj[fieldName] = fieldValue
			}
		}
		return obj

	case *typs.QLScalar:
		return typ.ParseValue(value)

	case *typs.QLEnum:
		return typ.ParseValue(value)

	default:
		panic("Must be input type")
	}
}
Example #2
0
func ASTFromValue(value interface{}, typ typs.QLType) lang.IValue {

	if typ, ok := typ.(*typs.QLNonNull); ok {
		return ASTFromValue(value, typ.OfType)
	}

	if IsNil(value) {
		return nil
	}

	val := reflect.ValueOf(value)
	val = reflect.Indirect(val)

	if val.Kind() == reflect.Array || val.Kind() == reflect.Slice {
		var itemType typs.QLType
		if typ, ok := typ.(*typs.QLList); ok {
			itemType = typ.OfType
		}

		values := []lang.IValue{}
		for i := 0; i < val.Len(); i++ {
			values = append(values, ASTFromValue(val.Index(i), itemType))
		}

		return &lang.ListValue{
			Values: values,
		}
	} else if typ, ok := typ.(*typs.QLList); ok {
		return ASTFromValue(value, typ.OfType)
	}

	if val.Kind() == reflect.Bool {
		return &lang.BooleanValue{
			Value: strconv.FormatBool(val.Bool()),
		}
	}

	if _, ok := typ.(*typs.QLScalar); ok {
		if val.Kind() == reflect.Int {
			return &lang.IntValue{
				Value: fmt.Sprintf("%v", val.Int()),
			}
		}

		if val.Kind() == reflect.Float64 {
			return &lang.FloatValue{
				Value: fmt.Sprintf("%v", val.Float()),
			}
		}
	}

	if val.Kind() == reflect.String {

		if _, ok := typ.(*typs.QLEnum); ok {
			matched, _ := regexp.MatchString(`^[_a-zA-Z][_a-zA-Z0-9]*$`, val.String())
			if matched {
				return &lang.EnumValue{
					Value: val.String(),
				}
			}
		}
		return &lang.StringValue{
			Value: val.String()[1 : val.Len()-1],
		}
	}

	v := val.Elem()

	fields := []*lang.ObjectField{}
	for i := 0; i < v.NumField(); i++ {
		valueField := v.Field(i)
		typeField := val.Type().Field(i)

		var fieldTyp typs.QLType

		if typ, ok := typ.(*typs.QLInputObject); ok {
			fieldDef := typ.GetFields()[typeField.Name]
			if fieldDef != nil {
				fieldTyp = fieldDef.Type
			}
		}

		fieldValue := ASTFromValue(valueField, fieldTyp)

		if fieldValue != nil {
			fields = append(fields, &lang.ObjectField{
				Name: &lang.Name{
					Value: typeField.Name,
				},
				Value: fieldValue,
			})
		}
	}

	return &lang.ObjectValue{
		Fields: fields,
	}

	return nil
}
Example #3
0
func (c *_Context) completeValue(
	returnType typs.QLType,
	fieldASTs []*lang.Field,
	info typs.QLResolveInfo,
	result interface{},
) interface{} {

	if returnType, ok := returnType.(*typs.QLNonNull); ok {
		completed := c.completeValue(returnType.OfType, fieldASTs, info, result)
		if completed == nil {
			nodes := make([]lang.INode, len(fieldASTs))
			for i, node := range fieldASTs {
				nodes[i] = node
			}
			panic(lang.NewQLError(
				fmt.Sprintf(
					`Cannot return null for non-nullable field %v.%v.`,
					info.ParentType, info.FieldName),
				nodes))
		}
		return completed
	}

	v := reflect.ValueOf(result)
	if result == nil {
		return nil
	}

	v = reflect.Indirect(v)
	t := v.Type()
	switch returnType := returnType.(type) {
	case *typs.QLList:
		if t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
			itemType := returnType.OfType
			list := make([]interface{}, t.NumField())
			for i, n := 0, t.NumField(); i < n; i++ {
				list[i] = c.completeValueCatchingError(itemType, fieldASTs, info, v.Field(i).Interface())
			}
			return list
		}
		panic("User Error: expected array of slice, but did not find one.")

	case *typs.QLScalar:
		if returnType.Serialize == nil {
			panic("Missing serialize method on type")
		}
		serializedResult := returnType.Serialize(result)
		if serializedResult == nil {
			return nil
		}
		return serializedResult

	case *typs.QLEnum:
		return returnType.Serialize(result)

	case *typs.QLObject:
		runtimeType := returnType
		subFieldASTs := map[string][]*lang.Field{}
		visitedFragmentNames := map[string]struct{}{}
		for _, fieldAST := range fieldASTs {
			selectionSet := fieldAST.SelectionSet
			if selectionSet != nil {
				subFieldASTs = c.collectFields(runtimeType, selectionSet, subFieldASTs, visitedFragmentNames)
			}
		}
		return c.executeFields(runtimeType, result, subFieldASTs)

	case typs.QLAbstractType:
		panic("not implemented")

	default:
		panic("unreachable")
	}
}