Example #1
0
File: node.go Project: kego/ke
func extractType(ctx context.Context, in system.Packed, rule *system.RuleWrapper) (*system.Type, error) {

	parentInterface := rule != nil && rule.Parent != nil && rule.Parent.Interface
	ruleInterface := rule != nil && rule.Struct != nil && rule.Struct.Interface

	if parentInterface && ruleInterface {
		return nil, kerr.New("TDXTPGVFAK", "Can't have interface type and interface rule at the same time")
	}

	if rule != nil && rule.Parent != nil && !parentInterface && !ruleInterface {
		// If we have a rule with the parent, and it's not an interface, then
		// we just return the parent type of the rule.
		return rule.Parent, nil
	}

	// if the rule is nil (e.g. unpacking into an unknown type) or the type is
	// an interface, we ensure the input is a map
	if rule == nil || parentInterface {
		if in == nil {
			return nil, nil
		}
		switch in.Type() {
		case system.J_NULL:
			// item is nil, so we don't know the concrete type yet.
			return nil, nil
		case system.J_MAP:
			break
		default:
			return nil, kerr.New("DLSQRFLINL", "Input %s should be J_MAP if rule is nil or an interface type", in.Type())
		}
	}

	// if the rule is an interface rule, we ensure the input is a map or a native value
	if ruleInterface {
		if in == nil {
			return nil, nil
		}
		switch in.Type() {
		case system.J_NULL:
			// item is nil, so we don't know the concrete type yet.
			return nil, nil
		case system.J_MAP:
			break
		case system.J_STRING, system.J_NUMBER, system.J_BOOL:
			// if the input value is a native value, we will be unpacking into
			// the parent type of the rule
			return rule.Parent, nil
		default:
			return nil, kerr.New("SNYLGBJYTM", "Input %s should be J_MAP, J_STRING, J_NUMBER or J_BOOL if rule is interface rule", in.Type())
		}
	}

	ob := in.Map()
	typeField, ok := ob["type"]
	if !ok {
		return nil, kerr.New("HBJVDKAKBJ", "Input must have type field if rule is nil or an interface type")
	}
	var r system.Reference
	if err := r.Unpack(ctx, typeField, false); err != nil {
		return nil, kerr.Wrap("YXHGIBXCOC", err)
	}
	t, ok := r.GetType(ctx)
	if !ok {
		return nil, kerr.New("IJFMJJWVCA", "Could not find type %s", r.Value())
	}
	return t, nil
}