1
2
3
4
5
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//! Definitions for the compiled Ruby macros.
//!
//! Since macros are rely on the C preprocessor, they are not automatically
//! available to Rust. This module compiles a tiny snippet of C code that is
//! used to generate the Ruby macros, so they can be used in Rust.

use std::os::raw::{c_char, c_long};

use crate::{ruby_value_type, ID, VALUE};

extern "C" {

    /// Queries if the given object is of given type.
    ///
    /// @param[in]  obj    An object.
    /// @param[in]  t      A type.
    /// @retval     true   `obj` is of type `t`.
    /// @retval     false  Otherwise.
    ///
    /// @internal
    ///
    /// This  function is  a super-duper  hot  path.  Optimised  targeting modern  C
    /// compilers and x86_64 architecture.
    #[link_name = "ruby_macros_RB_TYPE_P"]
    pub fn RB_TYPE_P(obj: VALUE, t: ruby_value_type) -> bool;

    /// Queries if the object is an instance of ::ruby_macros_cInteger.
    ///
    /// @param[in]  obj    Object in question.
    /// @retval     true   It is.
    /// @retval     false  It isn't.
    #[link_name = "ruby_macros_RB_INTEGER_TYPE_P"]
    pub fn RB_INTEGER_TYPE_P(obj: VALUE) -> bool;

    /// Queries if the object is an instance of ::ruby_macros_cFloat.
    ///
    /// @param[in]  obj    Object in question.
    /// @retval     true   It is.
    /// @retval     false  It isn't.
    #[link_name = "ruby_macros_RB_FLOAT_TYPE_P"]
    pub fn RB_FLOAT_TYPE_P(obj: VALUE) -> bool;

    /// Queries if the object is an instance of ::ruby_macros_cSymbol.
    ///
    /// @param[in]  obj    Object in question.
    /// @retval     true   It is.
    /// @retval     false  It isn't.
    #[link_name = "ruby_macros_SYMBOL_P"]
    pub fn SYMBOL_P(obj: VALUE) -> bool;

    /// Checks if the given object is nil.
    ///
    /// @param[in]  obj    An arbitrary ruby object.
    /// @retval     true   `obj` is ::Qnil.
    /// @retval     false  Anything else.
    #[link_name = "ruby_macros_NIL_P"]
    pub fn NIL_P(obj: VALUE) -> bool;

    /// Emulates Ruby's "if" statement.
    ///
    /// @param[in]  obj    An arbitrary ruby object.
    /// @retval     false  `obj` is either ::Qfalse or ::Qnil.
    /// @retval     true   Anything else.
    ///
    /// @internal
    ///
    /// It HAS to be `__attribute__((const))` in  order for clang to properly deduce
    /// `__builtin_assume()`.
    #[link_name = "ruby_macros_RB_TEST"]
    pub fn RB_TEST(obj: VALUE) -> bool;

    /// Allocates an instance of ::rb_cSymbol that has the given id.
    ///
    /// @param[in]  id           An id.
    /// @retval     Qfalse  No such id ever existed in the history.
    /// @retval     Otherwise    An allocated ::rb_cSymbol instance.
    #[link_name = "ruby_macros_ID2SYM"]
    pub fn ID2SYM(obj: ID) -> VALUE;

    /// Converts an instance of ::rb_cSymbol into an ::ID.
    ///
    /// @param[in]  obj            An instance of ::rb_cSymbol.
    /// @exception  rb_eTypeError  `obj` is not an instance of ::rb_cSymbol.
    /// @return     An ::ID of the identical symbol.
    #[link_name = "ruby_macros_SYM2ID"]
    pub fn SYM2ID(obj: ID) -> VALUE;

    /// Queries the contents pointer of the string.
    ///
    /// @param[in]  str  String in question.
    /// @return     Pointer to its contents.
    /// @pre        `str` must be an instance of ::RString.
    #[link_name = "ruby_macros_RSTRING_PTR"]
    pub fn RSTRING_PTR(obj: VALUE) -> *mut c_char;

    /// Queries the length of the string.
    ///
    /// @param[in]  str  String in question.
    /// @return     Its length, in bytes.
    /// @pre        `str` must be an instance of ::RString.
    #[link_name = "ruby_macros_RSTRING_LEN"]
    pub fn RSTRING_LEN(obj: VALUE) -> c_long;

    /// Queries the length of the array.
    ///
    /// @param[in]  a  Array in question.
    /// @return     Its number of elements.
    /// @pre        `a` must be an instance of ::RArray.
    #[link_name = "ruby_macros_RARRAY_LEN"]
    pub fn RARRAY_LEN(a: VALUE) -> c_long;

    /// Wild  use of  a  C  pointer.  This  function  accesses  the backend  storage
    /// directly.   This is  slower  than  #RARRAY_PTR_USE_TRANSIENT.  It  exercises
    /// extra manoeuvres  to protect our generational  GC.  Use of this  function is
    /// considered archaic.  Use a modern way instead.

    /// @param[in]  ary  An object of ::RArray.
    /// @return     The backend C array.

    /// @internal

    /// That said...  there are  extension libraries  in the wild  who uses  it.  We
    /// cannot but continue supporting.
    #[link_name = "ruby_macros_RARRAY_PTR"]
    pub fn RARRAY_PTR(a: VALUE) -> *const VALUE;
}