rb_sys/macros.rs
1//! Implementation of Ruby macros.
2//!
3//! Since macros are rely on the C preprocessor, or defined as `inline` C
4//! functions, they are not available when linking libruby. In order to use the
5//! libruby macros from Rust, `rb-sys` implements them using the following
6//! strategies:
7//!
8//! 1. For stable versions of Ruby, the macros are implemented as Rust functions
9//! 2. For ruby-head, the macros are implemented as C functions that are linked
10//! into the crate.
11
12#![allow(rustdoc::broken_intra_doc_links)]
13#![allow(non_upper_case_globals)]
14#![allow(non_snake_case)]
15
16use crate::rb_data_type_t;
17use crate::ruby_value_type;
18use crate::stable_api::get_default as api;
19use crate::StableApiDefinition;
20use crate::VALUE;
21use std::ffi::c_void;
22use std::os::raw::{c_char, c_long};
23
24/// Emulates Ruby's "if" statement.
25///
26/// - @param[in] obj An arbitrary ruby object.
27/// - @retval false `obj` is either ::RUBY_Qfalse or ::RUBY_Qnil.
28/// - @retval true Anything else.
29///
30/// ```
31/// use rb_sys::special_consts::*;
32///
33/// assert!(!TEST(Qfalse));
34/// assert!(!TEST(Qnil));
35/// assert!(TEST(Qtrue));
36/// ```
37#[inline]
38pub fn TEST<T: Into<VALUE>>(obj: T) -> bool {
39 api().rb_test(obj.into())
40}
41
42/// Checks if the given object is nil.
43///
44/// - @param[in] obj An arbitrary ruby object.
45/// - @retval true `obj` is ::RUBY_Qnil.
46/// - @retval false Anything else.
47///
48/// ### Example
49///
50/// ```
51/// use rb_sys::special_consts::*;
52///
53/// assert!(NIL_P(Qnil));
54/// assert!(!NIL_P(Qtrue));
55/// ```
56#[inline]
57pub fn NIL_P<T: Into<VALUE>>(obj: T) -> bool {
58 api().nil_p(obj.into())
59}
60
61/// Checks if the given object is a so-called Fixnum.
62///
63/// - @param[in] obj An arbitrary ruby object.
64/// - @retval true `obj` is a Fixnum.
65/// - @retval false Anything else.
66/// - @note Fixnum was a thing in the 20th century, but it is rather an implementation detail today.
67#[inline]
68pub fn FIXNUM_P<T: Into<VALUE>>(obj: T) -> bool {
69 api().fixnum_p(obj.into())
70}
71
72/// Checks if the given object is a static symbol.
73///
74/// - @param[in] obj An arbitrary ruby object.
75/// - @retval true `obj` is a static symbol
76/// - @retval false Anything else.
77/// - @see RB_DYNAMIC_SYM_P()
78/// - @see RB_SYMBOL_P()
79/// - @note These days there are static and dynamic symbols, just like we once had Fixnum/Bignum back in the old days.
80#[inline]
81pub fn STATIC_SYM_P<T: Into<VALUE>>(obj: T) -> bool {
82 api().static_sym_p(obj.into())
83}
84
85/// Get the backend storage of a Ruby array.
86///
87/// ### Safety
88///
89/// This function is unsafe because it dereferences a raw pointer and returns
90/// raw pointers to Ruby memory. The caller must ensure that the pointer stays live
91/// for the duration of usage the the underlying array (by either GC marking or
92/// keeping the RArray on the stack).
93///
94/// - @param[in] a An object of ::RArray.
95/// - @return Its backend storage.
96#[inline]
97pub unsafe fn RARRAY_CONST_PTR<T: Into<VALUE>>(obj: T) -> *const VALUE {
98 api().rarray_const_ptr(obj.into())
99}
100
101/// Get the length of a Ruby array.
102///
103/// ### Safety
104///
105/// This function is unsafe because it dereferences a raw pointer in order to
106/// access internal Ruby memory.
107///
108/// - @param[in] a An object of ::RArray.
109/// - @return Its length.
110#[inline]
111pub unsafe fn RARRAY_LEN<T: Into<VALUE>>(obj: T) -> c_long {
112 api().rarray_len(obj.into())
113}
114
115/// Get the length of a Ruby string.
116///
117/// ### Safety
118///
119/// This function is unsafe because it dereferences a raw pointer in order to
120/// access internal Ruby memory.
121///
122/// - @param[in] a An object of ::RString.
123/// - @return Its length.
124#[inline]
125pub unsafe fn RSTRING_LEN<T: Into<VALUE>>(obj: T) -> c_long {
126 api().rstring_len(obj.into())
127}
128
129/// Get the backend storage of a Ruby string.
130///
131/// ### Safety
132///
133/// This function is unsafe because it dereferences a raw pointer and returns
134/// raw pointers to Ruby memory.
135///
136/// - @param[in] a An object of ::RString.
137/// - @return Its backend storage
138#[inline]
139pub unsafe fn RSTRING_PTR<T: Into<VALUE>>(obj: T) -> *const c_char {
140 api().rstring_ptr(obj.into())
141}
142
143/// Checks if the given object is a so-called Flonum.
144///
145/// @param[in] obj An arbitrary ruby object.
146/// @retval true `obj` is a Flonum.
147/// @retval false Anything else.
148/// @see RB_FLOAT_TYPE_P()
149/// @note These days there are Flonums and non-Flonum floats, just like we
150/// once had Fixnum/Bignum back in the old days.
151#[inline]
152pub fn FLONUM_P<T: Into<VALUE>>(#[allow(unused)] obj: T) -> bool {
153 api().flonum_p(obj.into())
154}
155
156/// Checks if the given object is an immediate i.e. an object which has no
157/// corresponding storage inside of the object space.
158///
159/// @param[in] obj An arbitrary ruby object.
160/// @retval true `obj` is a Flonum.
161/// @retval false Anything else.
162/// @see RB_FLOAT_TYPE_P()
163/// @note The concept of "immediate" is purely C specific.
164#[inline]
165pub fn IMMEDIATE_P<T: Into<VALUE>>(obj: T) -> bool {
166 api().immediate_p(obj.into())
167}
168
169/// Checks if the given object is of enum ::ruby_special_consts.
170///
171/// @param[in] obj An arbitrary ruby object.
172/// @retval true `obj` is a special constant.
173/// @retval false Anything else.
174///
175/// ### Example
176///
177/// ```
178/// use rb_sys::special_consts::*;
179///
180/// assert!(SPECIAL_CONST_P(Qnil));
181/// assert!(SPECIAL_CONST_P(Qtrue));
182/// assert!(SPECIAL_CONST_P(Qfalse));
183/// ```
184#[inline]
185pub fn SPECIAL_CONST_P<T: Into<VALUE>>(obj: T) -> bool {
186 api().special_const_p(obj.into())
187}
188
189/// Queries the type of the object.
190///
191/// @param[in] obj Object in question.
192/// @pre `obj` must not be a special constant.
193/// @return The type of `obj`.
194///
195/// # Safety
196/// This function is unsafe because it could dereference a raw pointer when
197/// attemping to access the underlying [`RBasic`] struct.
198#[inline]
199pub unsafe fn RB_BUILTIN_TYPE(obj: VALUE) -> ruby_value_type {
200 api().builtin_type(obj)
201}
202
203/// Queries if the object is an instance of ::rb_cInteger.
204///
205/// @param[in] obj Object in question.
206/// @retval true It is.
207/// @retval false It isn't.
208///
209/// # Safety
210/// This function is unsafe because it could dereference a raw pointer when
211/// attemping to access the underlying [`RBasic`] struct.
212#[inline]
213pub unsafe fn RB_INTEGER_TYPE_P(obj: VALUE) -> bool {
214 api().integer_type_p(obj)
215}
216
217/// Queries if the object is a dynamic symbol.
218///
219/// @param[in] obj Object in question.
220/// @retval true It is.
221/// @retval false It isn't.
222///
223/// # Safety
224/// This function is unsafe because it could dereference a raw pointer when
225/// attemping to access the underlying [`RBasic`] struct.
226#[inline]
227pub unsafe fn RB_DYNAMIC_SYM_P(obj: VALUE) -> bool {
228 api().dynamic_sym_p(obj)
229}
230
231/// Queries if the object is an instance of ::rb_cSymbol.
232///
233/// @param[in] obj Object in question.
234/// @retval true It is.
235/// @retval false It isn't.
236///
237/// # Safety
238/// This function is unsafe because it could dereference a raw pointer when
239/// attemping to access the underlying [`RBasic`] struct.
240#[inline]
241pub unsafe fn RB_SYMBOL_P(obj: VALUE) -> bool {
242 api().symbol_p(obj)
243}
244
245/// Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
246///
247/// @param[in] obj Object in question.
248/// @return The type of `obj`.
249///
250/// # Safety
251/// This function is unsafe because it could dereference a raw pointer when
252/// attemping to access the underlying [`RBasic`] struct.
253#[inline]
254pub unsafe fn RB_TYPE(value: VALUE) -> ruby_value_type {
255 api().rb_type(value)
256}
257
258/// Queries if the given object is of given type.
259///
260/// @param[in] obj An object.
261/// @param[in] t A type.
262/// @retval true `obj` is of type `t`.
263/// @retval false Otherwise.
264///
265/// # Safety
266/// This function is unsafe because it could dereference a raw pointer when
267/// attemping to access the underlying [`RBasic`] struct.
268#[inline]
269#[cfg(ruby_engine = "mri")] // truffleruby provides its own implementation
270pub unsafe fn RB_TYPE_P(obj: VALUE, ty: ruby_value_type) -> bool {
271 api().type_p(obj, ty)
272}
273
274/// Queries if the object is an instance of ::rb_cFloat.
275///
276/// @param[in] obj Object in question.
277/// @retval true It is.
278/// @retval false It isn't.
279///
280/// # Safety
281/// This function is unsafe because it could dereference a raw pointer when
282/// attemping to access the underlying [`RBasic`] struct.
283#[inline]
284pub unsafe fn RB_FLOAT_TYPE_P(obj: VALUE) -> bool {
285 api().float_type_p(obj)
286}
287
288/// Checks if the given object is an RTypedData.
289///
290/// @param[in] obj Object in question.
291/// @retval true It is an RTypedData.
292/// @retval false It isn't an RTypedData.
293///
294/// # Safety
295/// This function is unsafe because it could dereference a raw pointer when
296/// accessing the underlying data structure.
297#[inline]
298pub unsafe fn RTYPEDDATA_P(obj: VALUE) -> bool {
299 api().rtypeddata_p(obj)
300}
301
302/// Checks if the given RTypedData is embedded.
303///
304/// @param[in] obj An RTypedData object.
305/// @retval true The data is embedded in the object itself.
306/// @retval false The data is stored separately.
307///
308/// # Safety
309/// This function is unsafe because it could dereference a raw pointer when
310/// accessing the underlying data structure. The caller must ensure the object
311/// is a valid RTypedData.
312#[inline]
313pub unsafe fn RTYPEDDATA_EMBEDDED_P(obj: VALUE) -> bool {
314 api().rtypeddata_embedded_p(obj)
315}
316
317/// Gets the data type information from an RTypedData object.
318///
319/// @param[in] obj An RTypedData object.
320/// @return Pointer to the rb_data_type_t structure for this object.
321///
322/// # Safety
323/// This function is unsafe because it dereferences a raw pointer to get
324/// access to the underlying data type. The caller must ensure the object
325/// is a valid RTypedData.
326#[inline]
327pub unsafe fn RTYPEDDATA_TYPE(obj: VALUE) -> *const rb_data_type_t {
328 api().rtypeddata_type(obj)
329}
330
331/// Gets the data pointer from an RTypedData object.
332///
333/// @param[in] obj An RTypedData object.
334/// @return Pointer to the wrapped C struct.
335///
336/// # Safety
337/// This function is unsafe because it dereferences a raw pointer to get
338/// access to the underlying data. The caller must ensure the object
339/// is a valid RTypedData.
340#[inline]
341pub unsafe fn RTYPEDDATA_GET_DATA(obj: VALUE) -> *mut c_void {
342 api().rtypeddata_get_data(obj)
343}