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 }