artichoke_backend/sys/
args.rs

1//! Helpers for retrieving args from mruby function calls.
2
3use super::mrb_aspec;
4
5/// Function requires n arguments.
6///
7/// ```text
8/// @param n
9///     The number of required arguments.
10/// ```
11#[inline]
12#[must_use]
13pub const fn mrb_args_req(n: u32) -> mrb_aspec {
14    // ```c
15    // #define MRB_ARGS_REQ(n)     ((mrb_aspec)((n)&0x1f) << 18)
16    // ```
17    (n & 0x1f) << 18
18}
19
20/// Function takes `n` optional arguments
21///
22/// ```text
23/// @param n
24///      The number of optional arguments.
25/// ```
26#[inline]
27#[must_use]
28pub const fn mrb_args_opt(n: u32) -> mrb_aspec {
29    // ```c
30    // #define MRB_ARGS_OPT(n)     ((mrb_aspec)((n)&0x1f) << 13)
31    // ```
32    (n & 0x1f) << 13
33}
34
35/// Function takes `n1` mandatory arguments and `n2` optional arguments
36///
37/// ```text
38/// @param n1
39///      The number of required arguments.
40/// @param n2
41///      The number of optional arguments.
42/// ```
43#[inline]
44#[must_use]
45pub const fn mrb_args_req_and_opt(n_req: u32, n_opt: u32) -> mrb_aspec {
46    // ```c
47    // #define MRB_ARGS_ARG(n1,n2)   (MRB_ARGS_REQ(n1)|MRB_ARGS_OPT(n2))
48    // ```
49    mrb_args_req(n_req) | mrb_args_opt(n_opt)
50}
51
52/// rest argument
53///
54/// ```ruby
55/// def foo(n1, *rest); end
56/// ```
57#[inline]
58#[must_use]
59pub const fn mrb_args_rest() -> mrb_aspec {
60    // ```c
61    // #define MRB_ARGS_REST()     ((mrb_aspec)(1 << 12))
62    // ```
63    1 << 12
64}
65
66/// required arguments after rest
67#[inline]
68#[must_use]
69pub const fn mrb_args_post(n: u32) -> mrb_aspec {
70    // ```c
71    // #define MRB_ARGS_POST(n)    ((mrb_aspec)((n)&0x1f) << 7)
72    // ```
73    (n & 0x1f) << 7
74}
75
76/// keyword arguments (`n` of keys, `kdict`)
77#[inline]
78#[must_use]
79pub const fn mrb_args_key(n1: u32, n2: u32) -> mrb_aspec {
80    // ```c
81    // #define MRB_ARGS_KEY(n1,n2) ((mrb_aspec)((((n1)&0x1f) << 2) | ((n2)?(1<<1):0)))
82    // ```
83    if n2 == 0 {
84        (n1 & 0x1f) << 2
85    } else {
86        ((n1 & 0x1f) << 2) | (1 << 1)
87    }
88}
89
90/// Function takes a block argument
91#[inline]
92#[must_use]
93pub const fn mrb_args_block() -> mrb_aspec {
94    // ```c
95    // #define MRB_ARGS_BLOCK()    ((mrb_aspec)1)
96    // ```
97    1
98}
99
100/// Function accepts any number of arguments
101#[inline]
102#[must_use]
103pub const fn mrb_args_any() -> mrb_aspec {
104    // ```c
105    // #define MRB_ARGS_ANY()      MRB_ARGS_REST()
106    // ```
107    mrb_args_rest()
108}
109
110/// Function accepts no arguments
111#[inline]
112#[must_use]
113pub const fn mrb_args_none() -> mrb_aspec {
114    // ```c
115    // #define MRB_ARGS_NONE()     ((mrb_aspec)0)
116    // ```
117    0
118}
119
120/// Format specifiers for [`mrb_get_args`](crate::sys::mrb_get_args) function.
121///
122/// `mrb_get_args` has the following prototype and returns the number of
123/// arguments parsed.
124///
125/// ```c
126/// MRB_API mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...)
127/// ```
128///
129/// `format` must be a C string composed of the following format specifiers:
130///
131/// ```text
132///   string  mruby type     C type                 note
133///   ----------------------------------------------------------------------------------------------
134///   o:      Object         `mrb_value`
135///   C:      class/module   `mrb_value`
136///   S:      String         `mrb_value`            when ! follows, the value may be nil
137///   A:      Array          `mrb_value`            when ! follows, the value may be nil
138///   H:      Hash           `mrb_value`            when ! follows, the value may be nil
139///   s:      String         `char*`,`mrb_int`      Receive two arguments; s! gives (NULL,0) for nil
140///   z:      String         `char*`                NUL terminated string; z! gives NULL for nil
141///   a:      Array          `mrb_value*`,`mrb_int` Receive two arguments; a! gives (NULL,0) for nil
142///   f:      Float          `mrb_float`
143///   i:      Integer        `mrb_int`
144///   b:      Boolean        `mrb_bool`
145///   n:      Symbol         `mrb_sym`
146///   d:      Data           `void*`,`mrb_data_type`  2nd argument will be used to check data type so it won't be modified
147///   I:      Inline struct  `void*`
148///   &:      Block          `mrb_value`            &! raises exception if no block given
149///   *:      rest argument  `mrb_value*`,`mrb_int` The rest of the arguments as an array; *! avoid copy of the stack
150///   |:      optional                              Following arguments are optional
151///   ?:      optional given `mrb_bool`             true if preceding argument (optional) is given
152/// ```
153pub mod specifiers {
154    /// Could be used to retrieve any type of argument
155    pub const OBJECT: &str = "o";
156
157    /// Retrieve a Class argument
158    pub const CLASS: &str = "C";
159
160    /// Retrieve a Module argument
161    pub const MODULE: &str = "C";
162
163    /// Retrieve a String argument
164    pub const STRING: &str = "S";
165
166    /// Retrieve a String argument or `nil`
167    pub const NILABLE_STRING: &str = "S!";
168
169    /// Retrieve an Array argument
170    pub const ARRAY: &str = "A";
171
172    /// Retrieve an Array argument or `nil`
173    pub const NILABLE_ARRAY: &str = "A!";
174
175    /// Retrieve a Hash argument
176    pub const HASH: &str = "H";
177
178    /// Retrieve a Hash argument or `nil`
179    pub const NILABLE_HASH: &str = "H!";
180
181    /// Retrieve a `CString` and its length. Usable like:
182    ///
183    /// ```c
184    /// mrb_get_args(mrb, "s", &ptr, &plen);
185    /// ```
186    pub const CSTRING_AND_LEN: &str = "s";
187
188    /// Retrieve a `CString` and its length. Gives (NULL, 0) for `nil`. Usable
189    /// like:
190    ///
191    /// ```c
192    /// mrb_get_args(mrb, "s", &ptr, &plen);
193    /// ```
194    pub const NULLABLE_CSTRING_AND_LEN: &str = "s!";
195
196    /// Retrieve a NUL-terminated `CString` argument
197    pub const CSTRING: &str = "z";
198
199    /// Retrieve a NUL-terminated `CString` argument. Gives NULL for `nil`
200    pub const NULLABLE_CSTRING: &str = "z!";
201
202    /// Receive two arguments, a C Array of `mrb_value`s and its length. Usable
203    /// like:
204    ///
205    /// ```c
206    /// mrb_get_args(mrb, "a", &ptr, &blen);
207    /// ```
208    pub const CARRAY_AND_LEN: &str = "a";
209
210    /// Receive two arguments, a C Array of `mrb_value`s and its length. Gives
211    /// (NULL, 0) for `nil`. Usable like:
212    ///
213    /// ```c
214    /// mrb_get_args(mrb, "a", &ptr, &blen);
215    /// ```
216    pub const NULLABLE_CARRAY_AND_LEN: &str = "a!";
217
218    /// Retrieve a Float argument.
219    pub const FLOAT: &str = "f";
220
221    /// Retrieve an Integer argument.
222    pub const INTEGER: &str = "i";
223
224    /// Retrieve a Boolean argument.
225    pub const BOOLEAN: &str = "b";
226
227    /// Retrieve a Symbol argument.
228    pub const SYMBOL: &str = "n";
229
230    /// Receive two arguments, a `void *` pointer to data and an
231    /// `mrb_data_type`.
232    ///
233    /// 2nd argument will be used to check data type so it won't be modified.
234    pub const DATA: &str = "d";
235
236    /// Internal, retrieve a `void *`.
237    pub const INLINE_STRUCT: &str = "I";
238
239    /// Retrieve a Block argument.
240    pub const BLOCK: &str = "&";
241
242    /// Retrieve a Block argument and raise an exception if none is given.
243    pub const BLOCK_REQUIRED: &str = "&!";
244
245    /// Retrieve the rest of arguments as an array; Usable like:
246    ///
247    /// ```c
248    /// mrb_get_args(mrb, "*", &argv, &argc);
249    /// ```
250    pub const REST: &str = "*";
251
252    /// Retrieve the rest of arguments as an array; avoid copy of the stack.
253    ///
254    /// ```c
255    /// mrb_get_args(mrb, "*", &argv, &argc);
256    /// ```
257    pub const REST_NO_COPY: &str = "*!";
258
259    /// The following args specified are optional.
260    pub const FOLLOWING_ARGS_OPTIONAL: &str = "|";
261
262    /// Retrieve a Boolean indicating whether the previous optional argument
263    /// was given.
264    pub const PREVIOUS_OPTIONAL_ARG_GIVEN: &str = "?";
265}