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::ruby_value_type;
17use crate::stable_api::get_default as api;
18use crate::StableApiDefinition;
19use crate::VALUE;
20use std::os::raw::{c_char, c_long};
21
22/// Emulates Ruby's "if" statement.
23///
24/// - @param[in] obj An arbitrary ruby object.
25/// - @retval false `obj` is either ::RUBY_Qfalse or ::RUBY_Qnil.
26/// - @retval true Anything else.
27///
28/// ```
29/// use rb_sys::special_consts::*;
30///
31/// assert!(!TEST(Qfalse));
32/// assert!(!TEST(Qnil));
33/// assert!(TEST(Qtrue));
34/// ```
35#[inline]
36pub fn TEST<T: Into<VALUE>>(obj: T) -> bool {
37 api().rb_test(obj.into())
38}
39
40/// Checks if the given object is nil.
41///
42/// - @param[in] obj An arbitrary ruby object.
43/// - @retval true `obj` is ::RUBY_Qnil.
44/// - @retval false Anything else.
45///
46/// ### Example
47///
48/// ```
49/// use rb_sys::special_consts::*;
50///
51/// assert!(NIL_P(Qnil));
52/// assert!(!NIL_P(Qtrue));
53/// ```
54#[inline]
55pub fn NIL_P<T: Into<VALUE>>(obj: T) -> bool {
56 api().nil_p(obj.into())
57}
58
59/// Checks if the given object is a so-called Fixnum.
60///
61/// - @param[in] obj An arbitrary ruby object.
62/// - @retval true `obj` is a Fixnum.
63/// - @retval false Anything else.
64/// - @note Fixnum was a thing in the 20th century, but it is rather an
65/// implementation detail today.
66#[inline]
67pub fn FIXNUM_P<T: Into<VALUE>>(obj: T) -> bool {
68 api().fixnum_p(obj.into())
69}
70
71/// Checks if the given object is a static symbol.
72///
73/// - @param[in] obj An arbitrary ruby object.
74/// - @retval true `obj` is a static symbol
75/// - @retval false Anything else.
76/// - @see RB_DYNAMIC_SYM_P()
77/// - @see RB_SYMBOL_P()
78/// - @note These days there are static and dynamic symbols, just like we
79/// 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}