Module: Rtype

Defined in:
ext/rtype/c/rtype.c

Defined Under Namespace

Modules: Behavior Classes: ArgumentTypeError, ReturnTypeError, TypeSignatureError

Constant Summary collapse

NATIVE_EXT_VERSION =
rb_str_new2(RTYPE_NATIVE_EXT_VERSION)

Instance Method Summary collapse

Instance Method Details

#assert_arguments_type(expected_args, args) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'ext/rtype/c/rtype.c', line 71

VALUE
rb_rtype_assert_arguments_type(VALUE self, VALUE expected_args, VALUE args) {
  // 'for' loop initial declarations are only allowed in c99 mode
  long i;
  long e_len = RARRAY_LEN(expected_args);
  for(i = 0; i < RARRAY_LEN(args); i++) {
    VALUE e, v;
    if(i >= e_len) {
      break;
    }
    e = rb_ary_entry(expected_args, i);
    v = rb_ary_entry(args, i);
    if( !RTEST(rb_rtype_valid(self, e, v)) ) {
      VALUE msg = rb_funcall(rb_mRtype, rb_intern("arg_type_error_message"), 3, LONG2FIX(i), e, v);
      rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
    }
  }
  return Qnil;
}

#assert_arguments_type_with_keywords(expected_args, args, expected_kwargs, kwargs) ⇒ Object



103
104
105
106
107
108
# File 'ext/rtype/c/rtype.c', line 103

VALUE
rb_rtype_assert_arguments_type_with_keywords(VALUE self, VALUE expected_args, VALUE args, VALUE expected_kwargs, VALUE kwargs) {
  rb_rtype_assert_arguments_type(self, expected_args, args);
  rb_hash_foreach(kwargs, kwargs_do_each, expected_kwargs);
  return Qnil;
}

#assert_return_type(expected, result) ⇒ Object



110
111
112
113
114
115
116
117
# File 'ext/rtype/c/rtype.c', line 110

VALUE
rb_rtype_assert_return_type(VALUE self, VALUE expected, VALUE result) {
  if( !RTEST(rb_rtype_valid(self, expected, result)) ) {
    VALUE msg = rb_funcall(rb_mRtype, rb_intern("type_error_message"), 2, expected, result);
    rb_raise(rb_eRtypeReturnTypeError, "for return:\n%s", StringValueCStr(msg));
  }
  return Qnil;
}

#valid?(expected, value) ⇒ Boolean

Returns:

  • (Boolean)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'ext/rtype/c/rtype.c', line 6

VALUE
rb_rtype_valid(VALUE self, VALUE expected, VALUE value) {
  long i;
  VALUE e_keys;
  VALUE v_keys;
  
  switch(TYPE(expected)) {
    case T_MODULE:
    case T_CLASS:
      return rb_obj_is_kind_of(value, expected) ? Qtrue : Qfalse;
    case T_SYMBOL:
      return rb_respond_to(value, rb_to_id(expected)) ? Qtrue : Qfalse;
    case T_REGEXP:
      return rb_reg_match( expected, rb_funcall(value, id_to_s, 0) ) != Qnil ? Qtrue : Qfalse;
    case T_HASH:
      if( !RB_TYPE_P(value, T_HASH) ) {
        return Qfalse;
      }
      e_keys = rb_funcall(expected, id_keys, 0);
      v_keys = rb_funcall(value, id_keys, 0);
      if( !RTEST(rb_funcall(e_keys, id_eqeq, 1, v_keys)) ) {
        return Qfalse;
      }
      
      for(i = 0; i < RARRAY_LEN(e_keys); i++) {
        VALUE e_k = rb_ary_entry(e_keys, i);
        VALUE e_v = rb_hash_aref(expected, e_k);
        if(rb_rtype_valid(self, e_v, rb_hash_aref(value, e_k)) == Qfalse) {
          return Qfalse;
        }
      }
      return Qtrue;
    case T_ARRAY:
      for(i = 0; i < RARRAY_LEN(expected); i++) {
        VALUE e = rb_ary_entry(expected, i);
        VALUE valid = rb_rtype_valid(self, e, value);
        if(valid == Qtrue) {
          return Qtrue;
        }
      }
      return Qfalse;
    case T_TRUE:
      return RTEST(value) ? Qtrue : Qfalse;
    case T_FALSE:
      return !RTEST(value) ? Qtrue : Qfalse;
    case T_NIL:
      return value == Qnil;
    default:
      if(rb_obj_is_kind_of(expected, rb_cRange)) {
        return rb_funcall(expected, id_include, 1, value);
      }
      else if(rb_obj_is_kind_of(expected, rb_cProc)) {
        return RTEST(rb_funcall(expected, id_call, 1, value)) ? Qtrue : Qfalse;
      }
      else if( RTEST(rb_obj_is_kind_of(expected, rb_cRtypeBehaviorBase)) ) {
        return rb_funcall(expected, id_valid, 1, value);
      }
      else {
        VALUE str = rb_any_to_s(expected);
        rb_raise(rb_eRtypeTypeSignatureError, "Invalid type signature: Unknown type behavior %s", StringValueCStr(str));
        return Qfalse;
      }
  }
}