artichoke_backend/extn/core/string/
mruby.rs

1use std::ffi::CStr;
2
3use crate::extn::core::string::{self, trampoline};
4use crate::extn::prelude::*;
5
6const STRING_CSTR: &CStr = c"String";
7static STRING_RUBY_SOURCE: &[u8] = include_bytes!("string.rb");
8
9pub fn init(interp: &mut Artichoke) -> InitializeResult<()> {
10    if interp.is_class_defined::<string::String>() {
11        return Ok(());
12    }
13
14    let spec = class::Spec::new("String", STRING_CSTR, None, None)?;
15    class::Builder::for_spec(interp, &spec)
16        .add_method("*", string_mul, sys::mrb_args_req(1))?
17        .add_method("+", string_add, sys::mrb_args_req(1))?
18        .add_method("<<", string_append, sys::mrb_args_req(1))?
19        .add_method("<=>", string_cmp_rocket, sys::mrb_args_req(1))?
20        .add_method("==", string_equals_equals, sys::mrb_args_req(1))?
21        .add_method("[]", string_aref, sys::mrb_args_req(1))?
22        .add_method("[]=", string_aset, sys::mrb_args_any())?
23        .add_method("ascii_only?", string_ascii_only, sys::mrb_args_none())?
24        .add_method("b", string_b, sys::mrb_args_none())?
25        .add_method("byteindex", string_byteindex, sys::mrb_args_req_and_opt(1, 1))?
26        .add_method("byterindex", string_byterindex, sys::mrb_args_req_and_opt(1, 1))?
27        .add_method("bytes", string_bytes, sys::mrb_args_none())? // This does not support the deprecated block form
28        .add_method("bytesize", string_bytesize, sys::mrb_args_none())?
29        .add_method("byteslice", string_byteslice, sys::mrb_args_req_and_opt(1, 1))?
30        .add_method("capitalize", string_capitalize, sys::mrb_args_any())?
31        .add_method("capitalize!", string_capitalize_bang, sys::mrb_args_any())?
32        .add_method("casecmp", string_casecmp_ascii, sys::mrb_args_req(1))?
33        .add_method("casecmp?", string_casecmp_unicode, sys::mrb_args_req(1))?
34        .add_method("center", string_center, sys::mrb_args_req_and_opt(1, 1))?
35        .add_method("chars", string_chars, sys::mrb_args_none())? // This does not support the deprecated block form
36        .add_method("chomp", string_chomp, sys::mrb_args_opt(1))?
37        .add_method("chomp!", string_chomp_bang, sys::mrb_args_opt(1))?
38        .add_method("chop", string_chop, sys::mrb_args_none())?
39        .add_method("chop!", string_chop_bang, sys::mrb_args_none())?
40        .add_method("chr", string_chr, sys::mrb_args_none())?
41        .add_method("clear", string_clear, sys::mrb_args_none())?
42        .add_method("codepoints", string_codepoints, sys::mrb_args_none())? // This does not support the deprecated block form
43        .add_method("downcase", string_downcase, sys::mrb_args_any())?
44        .add_method("downcase!", string_downcase_bang, sys::mrb_args_any())?
45        .add_method("empty?", string_empty, sys::mrb_args_none())?
46        .add_method("end_with?", string_end_with, sys::mrb_args_rest())?
47        .add_method("eql?", string_eql, sys::mrb_args_req(1))?
48        .add_method("getbyte", string_getbyte, sys::mrb_args_req(1))?
49        .add_method("hash", string_hash, sys::mrb_args_none())?
50        .add_method("include?", string_include, sys::mrb_args_req(1))?
51        .add_method("index", string_index, sys::mrb_args_req_and_opt(1, 1))?
52        .add_method("initialize", string_initialize, sys::mrb_args_opt(1))? // TODO: support encoding and capacity kwargs
53        .add_method("initialize_copy", string_initialize_copy, sys::mrb_args_req(1))?
54        .add_method("inspect", string_inspect, sys::mrb_args_none())?
55        .add_method("intern", string_intern, sys::mrb_args_none())?
56        .add_method("length", string_length, sys::mrb_args_none())?
57        .add_method("ord", string_ord, sys::mrb_args_none())?
58        .add_method("replace", string_replace, sys::mrb_args_req(1))?
59        .add_method("reverse", string_reverse, sys::mrb_args_none())?
60        .add_method("reverse!", string_reverse_bang, sys::mrb_args_none())?
61        .add_method("rindex", string_rindex, sys::mrb_args_req_and_opt(1, 1))?
62        .add_method("scan", string_scan, sys::mrb_args_req(1))?
63        .add_method("setbyte", string_setbyte, sys::mrb_args_req(2))?
64        .add_method("size", string_length, sys::mrb_args_none())?
65        .add_method("slice", string_aref, sys::mrb_args_req(1))?
66        .add_method("slice!", string_slice_bang, sys::mrb_args_req(1))?
67        .add_method("split", string_split, sys::mrb_args_opt(2))?
68        .add_method("start_with?", string_start_with, sys::mrb_args_rest())?
69        .add_method("swapcase", string_swapcase, sys::mrb_args_any())?
70        .add_method("swapcase!", string_swapcase_bang, sys::mrb_args_any())?
71        .add_method("to_f", string_to_f, sys::mrb_args_none())?
72        .add_method("to_i", string_to_i, sys::mrb_args_opt(1))?
73        .add_method("to_s", string_to_s, sys::mrb_args_none())?
74        .add_method("to_sym", string_intern, sys::mrb_args_none())?
75        .add_method("upcase", string_upcase, sys::mrb_args_any())?
76        .add_method("upcase!", string_upcase_bang, sys::mrb_args_any())?
77        .add_method("valid_encoding?", string_valid_encoding, sys::mrb_args_none())?
78        .define()?;
79    interp.def_class::<string::String>(spec)?;
80    interp.eval(STRING_RUBY_SOURCE)?;
81
82    Ok(())
83}
84
85unsafe extern "C-unwind" fn string_mul(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
86    let other = mrb_get_args!(mrb, required = 1);
87    unwrap_interpreter!(mrb, to => guard);
88    let value = Value::from(slf);
89    let other = Value::from(other);
90    let result = trampoline::mul(&mut guard, value, other);
91    match result {
92        Ok(value) => value.inner(),
93        Err(exception) => {
94            // SAFETY: only Copy objects remain on the stack
95            unsafe { error::raise(guard, exception) }
96        }
97    }
98}
99
100unsafe extern "C-unwind" fn string_add(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
101    let other = mrb_get_args!(mrb, required = 1);
102    unwrap_interpreter!(mrb, to => guard);
103    let value = Value::from(slf);
104    let other = Value::from(other);
105    let result = trampoline::add(&mut guard, value, other);
106    match result {
107        Ok(value) => value.inner(),
108        Err(exception) => {
109            // SAFETY: only Copy objects remain on the stack
110            unsafe { error::raise(guard, exception) }
111        }
112    }
113}
114
115unsafe extern "C-unwind" fn string_append(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
116    let other = mrb_get_args!(mrb, required = 1);
117    unwrap_interpreter!(mrb, to => guard);
118    let value = Value::from(slf);
119    let other = Value::from(other);
120    let result = trampoline::append(&mut guard, value, other);
121    match result {
122        Ok(value) => value.inner(),
123        Err(exception) => {
124            // SAFETY: only Copy objects remain on the stack
125            unsafe { error::raise(guard, exception) }
126        }
127    }
128}
129
130unsafe extern "C-unwind" fn string_cmp_rocket(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
131    let other = mrb_get_args!(mrb, required = 1);
132    unwrap_interpreter!(mrb, to => guard);
133    let value = Value::from(slf);
134    let other = Value::from(other);
135    let result = trampoline::cmp_rocket(&mut guard, value, other);
136    match result {
137        Ok(value) => value.inner(),
138        Err(exception) => {
139            // SAFETY: only Copy objects remain on the stack
140            unsafe { error::raise(guard, exception) }
141        }
142    }
143}
144
145unsafe extern "C-unwind" fn string_equals_equals(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
146    let other = mrb_get_args!(mrb, required = 1);
147    unwrap_interpreter!(mrb, to => guard);
148    let value = Value::from(slf);
149    let other = Value::from(other);
150    let result = trampoline::equals_equals(&mut guard, value, other);
151    match result {
152        Ok(value) => value.inner(),
153        Err(exception) => {
154            // SAFETY: only Copy objects remain on the stack
155            unsafe { error::raise(guard, exception) }
156        }
157    }
158}
159
160unsafe extern "C-unwind" fn string_aref(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
161    let (first, second) = mrb_get_args!(mrb, required = 1, optional = 1);
162    unwrap_interpreter!(mrb, to => guard);
163    let value = Value::from(slf);
164    let first = Value::from(first);
165    let second = second.map(Value::from);
166    let result = trampoline::aref(&mut guard, value, first, second);
167    match result {
168        Ok(value) => value.inner(),
169        Err(exception) => {
170            // SAFETY: only Copy objects remain on the stack
171            unsafe { error::raise(guard, exception) }
172        }
173    }
174}
175
176unsafe extern "C-unwind" fn string_aset(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
177    mrb_get_args!(mrb, none);
178    unwrap_interpreter!(mrb, to => guard);
179    let value = Value::from(slf);
180    let result = trampoline::aset(&mut guard, value);
181    match result {
182        Ok(value) => value.inner(),
183        Err(exception) => {
184            // SAFETY: only Copy objects remain on the stack
185            unsafe { error::raise(guard, exception) }
186        }
187    }
188}
189
190unsafe extern "C-unwind" fn string_ascii_only(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
191    mrb_get_args!(mrb, none);
192    unwrap_interpreter!(mrb, to => guard);
193    let value = Value::from(slf);
194    let result = trampoline::is_ascii_only(&mut guard, value);
195    match result {
196        Ok(value) => value.inner(),
197        Err(exception) => {
198            // SAFETY: only Copy objects remain on the stack
199            unsafe { error::raise(guard, exception) }
200        }
201    }
202}
203
204unsafe extern "C-unwind" fn string_b(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
205    mrb_get_args!(mrb, none);
206    unwrap_interpreter!(mrb, to => guard);
207    let value = Value::from(slf);
208    let result = trampoline::b(&mut guard, value);
209    match result {
210        Ok(value) => value.inner(),
211        Err(exception) => {
212            // SAFETY: only Copy objects remain on the stack
213            unsafe { error::raise(guard, exception) }
214        }
215    }
216}
217
218unsafe extern "C-unwind" fn string_byteindex(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
219    let (substring, offset) = mrb_get_args!(mrb, required = 1, optional = 1);
220    unwrap_interpreter!(mrb, to => guard);
221    let value = Value::from(slf);
222    let substring = Value::from(substring);
223    let offset = offset.map(Value::from);
224    let result = trampoline::byteindex(&mut guard, value, substring, offset);
225    match result {
226        Ok(value) => value.inner(),
227        Err(exception) => {
228            // SAFETY: only Copy objects remain on the stack
229            unsafe { error::raise(guard, exception) }
230        }
231    }
232}
233
234unsafe extern "C-unwind" fn string_byterindex(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
235    let (substring, offset) = mrb_get_args!(mrb, required = 1, optional = 1);
236    unwrap_interpreter!(mrb, to => guard);
237    let value = Value::from(slf);
238    let substring = Value::from(substring);
239    let offset = offset.map(Value::from);
240    let result = trampoline::byterindex(&mut guard, value, substring, offset);
241    match result {
242        Ok(value) => value.inner(),
243        Err(exception) => {
244            // SAFETY: only Copy objects remain on the stack
245            unsafe { error::raise(guard, exception) }
246        }
247    }
248}
249
250unsafe extern "C-unwind" fn string_bytes(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
251    mrb_get_args!(mrb, none);
252    unwrap_interpreter!(mrb, to => guard);
253    let value = Value::from(slf);
254    let result = trampoline::bytes(&mut guard, value);
255    match result {
256        Ok(value) => value.inner(),
257        Err(exception) => {
258            // SAFETY: only Copy objects remain on the stack
259            unsafe { error::raise(guard, exception) }
260        }
261    }
262}
263
264unsafe extern "C-unwind" fn string_bytesize(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
265    mrb_get_args!(mrb, none);
266    unwrap_interpreter!(mrb, to => guard);
267    let value = Value::from(slf);
268    let result = trampoline::bytesize(&mut guard, value);
269    match result {
270        Ok(value) => value.inner(),
271        Err(exception) => {
272            // SAFETY: only Copy objects remain on the stack
273            unsafe { error::raise(guard, exception) }
274        }
275    }
276}
277
278unsafe extern "C-unwind" fn string_byteslice(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
279    let (index, length) = mrb_get_args!(mrb, required = 1, optional = 1);
280    unwrap_interpreter!(mrb, to => guard);
281    let value = Value::from(slf);
282    let index = Value::from(index);
283    let length = length.map(Value::from);
284    let result = trampoline::byteslice(&mut guard, value, index, length);
285    match result {
286        Ok(value) if value.is_nil() => value.inner(),
287        Ok(value) => {
288            let rclass = sys::mrb_sys_class_of_value(mrb, slf);
289            let value = value.inner();
290            let target_rbasic = value.value.p.cast::<sys::RBasic>();
291
292            // Copy `RClass` from source class to newly allocated `Array`.
293            (*target_rbasic).c = rclass;
294
295            value
296        }
297        Err(exception) => {
298            // SAFETY: only Copy objects remain on the stack
299            unsafe { error::raise(guard, exception) }
300        }
301    }
302}
303
304unsafe extern "C-unwind" fn string_capitalize(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
305    // FIXME: Support receiving case mapping options:
306    // <https://ruby-doc.org/core-3.1.2/doc/case_mapping_rdoc.html>
307    // <https://github.com/artichoke/artichoke/issues/2833>
308    mrb_get_args!(mrb, none);
309    unwrap_interpreter!(mrb, to => guard);
310    let value = Value::from(slf);
311    let result = trampoline::capitalize(&mut guard, value);
312    match result {
313        Ok(value) => value.inner(),
314        Err(exception) => {
315            // SAFETY: only Copy objects remain on the stack
316            unsafe { error::raise(guard, exception) }
317        }
318    }
319}
320
321unsafe extern "C-unwind" fn string_capitalize_bang(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
322    // FIXME: Support receiving case mapping options:
323    // <https://ruby-doc.org/core-3.1.2/doc/case_mapping_rdoc.html>
324    // <https://github.com/artichoke/artichoke/issues/2833>
325    mrb_get_args!(mrb, none);
326    unwrap_interpreter!(mrb, to => guard);
327    let value = Value::from(slf);
328    let result = trampoline::capitalize_bang(&mut guard, value);
329    match result {
330        Ok(value) => value.inner(),
331        Err(exception) => {
332            // SAFETY: only Copy objects remain on the stack
333            unsafe { error::raise(guard, exception) }
334        }
335    }
336}
337
338unsafe extern "C-unwind" fn string_casecmp_ascii(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
339    let other = mrb_get_args!(mrb, required = 1);
340    unwrap_interpreter!(mrb, to => guard);
341    let value = Value::from(slf);
342    let other = Value::from(other);
343    let result = trampoline::casecmp_ascii(&mut guard, value, other);
344    match result {
345        Ok(value) => value.inner(),
346        Err(exception) => {
347            // SAFETY: only Copy objects remain on the stack
348            unsafe { error::raise(guard, exception) }
349        }
350    }
351}
352
353unsafe extern "C-unwind" fn string_casecmp_unicode(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
354    let other = mrb_get_args!(mrb, required = 1);
355    unwrap_interpreter!(mrb, to => guard);
356    let value = Value::from(slf);
357    let other = Value::from(other);
358    let result = trampoline::casecmp_unicode(&mut guard, value, other);
359    match result {
360        Ok(value) => value.inner(),
361        Err(exception) => {
362            // SAFETY: only Copy objects remain on the stack
363            unsafe { error::raise(guard, exception) }
364        }
365    }
366}
367
368unsafe extern "C-unwind" fn string_center(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
369    let (width, padstr) = mrb_get_args!(mrb, required = 1, optional = 1);
370    unwrap_interpreter!(mrb, to => guard);
371    let value = Value::from(slf);
372    let width = Value::from(width);
373    let padstr = padstr.map(Value::from);
374    let result = trampoline::center(&mut guard, value, width, padstr);
375    match result {
376        Ok(value) => value.inner(),
377        Err(exception) => {
378            // SAFETY: only Copy objects remain on the stack
379            unsafe { error::raise(guard, exception) }
380        }
381    }
382}
383
384unsafe extern "C-unwind" fn string_chars(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
385    mrb_get_args!(mrb, none);
386    unwrap_interpreter!(mrb, to => guard);
387    let value = Value::from(slf);
388    let result = trampoline::chars(&mut guard, value);
389    match result {
390        Ok(value) => value.inner(),
391        Err(exception) => {
392            // SAFETY: only Copy objects remain on the stack
393            unsafe { error::raise(guard, exception) }
394        }
395    }
396}
397
398unsafe extern "C-unwind" fn string_chomp(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
399    let separator = mrb_get_args!(mrb, optional = 1);
400    unwrap_interpreter!(mrb, to => guard);
401    let value = Value::from(slf);
402    let separator = separator.map(Value::from);
403    let result = trampoline::chomp(&mut guard, value, separator);
404    match result {
405        Ok(value) => {
406            let rclass = sys::mrb_sys_class_of_value(mrb, slf);
407            let value = value.inner();
408            let target_rbasic = value.value.p.cast::<sys::RBasic>();
409
410            // Copy `RClass` from source class to newly allocated `Array`.
411            (*target_rbasic).c = rclass;
412
413            value
414        }
415        Err(exception) => {
416            // SAFETY: only Copy objects remain on the stack
417            unsafe { error::raise(guard, exception) }
418        }
419    }
420}
421
422unsafe extern "C-unwind" fn string_chomp_bang(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
423    let separator = mrb_get_args!(mrb, optional = 1);
424    unwrap_interpreter!(mrb, to => guard);
425    let value = Value::from(slf);
426    let separator = separator.map(Value::from);
427    let result = trampoline::chomp_bang(&mut guard, value, separator);
428    match result {
429        Ok(value) => value.inner(),
430        Err(exception) => {
431            // SAFETY: only Copy objects remain on the stack
432            unsafe { error::raise(guard, exception) }
433        }
434    }
435}
436
437unsafe extern "C-unwind" fn string_chop(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
438    mrb_get_args!(mrb, none);
439    unwrap_interpreter!(mrb, to => guard);
440    let value = Value::from(slf);
441    let result = trampoline::chop(&mut guard, value);
442    match result {
443        Ok(value) => {
444            let rclass = sys::mrb_sys_class_of_value(mrb, slf);
445            let value = value.inner();
446            let target_rbasic = value.value.p.cast::<sys::RBasic>();
447
448            // Copy `RClass` from source class to newly allocated `Array`.
449            (*target_rbasic).c = rclass;
450
451            value
452        }
453        Err(exception) => {
454            // SAFETY: only Copy objects remain on the stack
455            unsafe { error::raise(guard, exception) }
456        }
457    }
458}
459
460unsafe extern "C-unwind" fn string_chop_bang(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
461    mrb_get_args!(mrb, none);
462    unwrap_interpreter!(mrb, to => guard);
463    let value = Value::from(slf);
464    let result = trampoline::chop_bang(&mut guard, value);
465    match result {
466        Ok(value) => value.inner(),
467        Err(exception) => {
468            // SAFETY: only Copy objects remain on the stack
469            unsafe { error::raise(guard, exception) }
470        }
471    }
472}
473
474unsafe extern "C-unwind" fn string_chr(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
475    mrb_get_args!(mrb, none);
476    unwrap_interpreter!(mrb, to => guard);
477    let value = Value::from(slf);
478    let result = trampoline::chr(&mut guard, value);
479    match result {
480        Ok(value) => value.inner(),
481        Err(exception) => {
482            // SAFETY: only Copy objects remain on the stack
483            unsafe { error::raise(guard, exception) }
484        }
485    }
486}
487
488unsafe extern "C-unwind" fn string_clear(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
489    mrb_get_args!(mrb, none);
490    unwrap_interpreter!(mrb, to => guard);
491    let value = Value::from(slf);
492    let result = trampoline::clear(&mut guard, value);
493    match result {
494        Ok(value) => value.inner(),
495        Err(exception) => {
496            // SAFETY: only Copy objects remain on the stack
497            unsafe { error::raise(guard, exception) }
498        }
499    }
500}
501
502unsafe extern "C-unwind" fn string_codepoints(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
503    mrb_get_args!(mrb, none);
504    unwrap_interpreter!(mrb, to => guard);
505    let value = Value::from(slf);
506    let result = trampoline::codepoints(&mut guard, value);
507    match result {
508        Ok(value) => value.inner(),
509        Err(exception) => {
510            // SAFETY: only Copy objects remain on the stack
511            unsafe { error::raise(guard, exception) }
512        }
513    }
514}
515
516unsafe extern "C-unwind" fn string_downcase(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
517    // FIXME: Support receiving case mapping options:
518    // <https://ruby-doc.org/core-3.1.2/doc/case_mapping_rdoc.html>
519    // <https://github.com/artichoke/artichoke/issues/2833>
520    mrb_get_args!(mrb, none);
521    unwrap_interpreter!(mrb, to => guard);
522    let value = Value::from(slf);
523    let result = trampoline::downcase(&mut guard, value);
524    match result {
525        Ok(value) => value.inner(),
526        Err(exception) => {
527            // SAFETY: only Copy objects remain on the stack
528            unsafe { error::raise(guard, exception) }
529        }
530    }
531}
532
533unsafe extern "C-unwind" fn string_downcase_bang(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
534    // FIXME: Support receiving case mapping options:
535    // <https://ruby-doc.org/core-3.1.2/doc/case_mapping_rdoc.html>
536    // <https://github.com/artichoke/artichoke/issues/2833>
537    mrb_get_args!(mrb, none);
538    unwrap_interpreter!(mrb, to => guard);
539    let value = Value::from(slf);
540    let result = trampoline::downcase_bang(&mut guard, value);
541    match result {
542        Ok(value) => value.inner(),
543        Err(exception) => {
544            // SAFETY: only Copy objects remain on the stack
545            unsafe { error::raise(guard, exception) }
546        }
547    }
548}
549
550unsafe extern "C-unwind" fn string_empty(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
551    mrb_get_args!(mrb, none);
552    unwrap_interpreter!(mrb, to => guard);
553    let value = Value::from(slf);
554    let result = trampoline::is_empty(&mut guard, value);
555    match result {
556        Ok(value) => value.inner(),
557        Err(exception) => {
558            // SAFETY: only Copy objects remain on the stack
559            unsafe { error::raise(guard, exception) }
560        }
561    }
562}
563
564unsafe extern "C-unwind" fn string_end_with(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
565    let suffixes = mrb_get_args!(mrb, *args);
566    unwrap_interpreter!(mrb, to => guard);
567    let value = Value::from(slf);
568    let suffixes = suffixes.iter().map(|&other| Value::from(other));
569    let result = trampoline::end_with(&mut guard, value, suffixes);
570    match result {
571        Ok(result) => result.inner(),
572        Err(exception) => {
573            // SAFETY: only Copy objects remain on the stack
574            unsafe { error::raise(guard, exception) }
575        }
576    }
577}
578
579unsafe extern "C-unwind" fn string_eql(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
580    let other = mrb_get_args!(mrb, required = 1);
581    unwrap_interpreter!(mrb, to => guard);
582    let value = Value::from(slf);
583    let other = Value::from(other);
584    let result = trampoline::eql(&mut guard, value, other);
585    match result {
586        Ok(value) => value.inner(),
587        Err(exception) => {
588            // SAFETY: only Copy objects remain on the stack
589            unsafe { error::raise(guard, exception) }
590        }
591    }
592}
593
594unsafe extern "C-unwind" fn string_getbyte(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
595    let index = mrb_get_args!(mrb, required = 1);
596    unwrap_interpreter!(mrb, to => guard);
597    let value = Value::from(slf);
598    let index = Value::from(index);
599    let result = trampoline::getbyte(&mut guard, value, index);
600    match result {
601        Ok(value) => value.inner(),
602        Err(exception) => {
603            // SAFETY: only Copy objects remain on the stack
604            unsafe { error::raise(guard, exception) }
605        }
606    }
607}
608
609unsafe extern "C-unwind" fn string_hash(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
610    mrb_get_args!(mrb, none);
611    unwrap_interpreter!(mrb, to => guard);
612    let value = Value::from(slf);
613    let result = trampoline::hash(&mut guard, value);
614    match result {
615        Ok(value) => value.inner(),
616        Err(exception) => {
617            // SAFETY: only Copy objects remain on the stack
618            unsafe { error::raise(guard, exception) }
619        }
620    }
621}
622
623unsafe extern "C-unwind" fn string_include(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
624    let other = mrb_get_args!(mrb, required = 1);
625    unwrap_interpreter!(mrb, to => guard);
626    let value = Value::from(slf);
627    let other = Value::from(other);
628    let result = trampoline::include(&mut guard, value, other);
629    match result {
630        Ok(value) => value.inner(),
631        Err(exception) => {
632            // SAFETY: only Copy objects remain on the stack
633            unsafe { error::raise(guard, exception) }
634        }
635    }
636}
637
638unsafe extern "C-unwind" fn string_index(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
639    let (needle, offset) = mrb_get_args!(mrb, required = 1, optional = 1);
640    unwrap_interpreter!(mrb, to => guard);
641    let value = Value::from(slf);
642    let needle = Value::from(needle);
643    let offset = offset.map(Value::from);
644    let result = trampoline::index(&mut guard, value, needle, offset);
645    match result {
646        Ok(value) => value.inner(),
647        Err(exception) => {
648            // SAFETY: only Copy objects remain on the stack
649            unsafe { error::raise(guard, exception) }
650        }
651    }
652}
653
654unsafe extern "C-unwind" fn string_initialize(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
655    let s = mrb_get_args!(mrb, optional = 1);
656    unwrap_interpreter!(mrb, to => guard);
657    let value = Value::from(slf);
658    let s = s.map(Value::from);
659    let result = trampoline::initialize(&mut guard, value, s);
660    match result {
661        Ok(value) => value.inner(),
662        Err(exception) => {
663            // SAFETY: only Copy objects remain on the stack
664            unsafe { error::raise(guard, exception) }
665        }
666    }
667}
668
669unsafe extern "C-unwind" fn string_initialize_copy(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
670    let other = mrb_get_args!(mrb, required = 1);
671    unwrap_interpreter!(mrb, to => guard);
672    let value = Value::from(slf);
673    let other = Value::from(other);
674    let result = trampoline::initialize_copy(&mut guard, value, other);
675    match result {
676        Ok(value) => value.inner(),
677        Err(exception) => {
678            // SAFETY: only Copy objects remain on the stack
679            unsafe { error::raise(guard, exception) }
680        }
681    }
682}
683
684unsafe extern "C-unwind" fn string_inspect(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
685    mrb_get_args!(mrb, none);
686    unwrap_interpreter!(mrb, to => guard);
687    let value = Value::from(slf);
688    let result = trampoline::inspect(&mut guard, value);
689    match result {
690        Ok(value) => value.inner(),
691        Err(exception) => {
692            // SAFETY: only Copy objects remain on the stack
693            unsafe { error::raise(guard, exception) }
694        }
695    }
696}
697
698unsafe extern "C-unwind" fn string_intern(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
699    mrb_get_args!(mrb, none);
700    unwrap_interpreter!(mrb, to => guard);
701    let value = Value::from(slf);
702    let result = trampoline::intern(&mut guard, value);
703    match result {
704        Ok(value) => value.inner(),
705        Err(exception) => {
706            // SAFETY: only Copy objects remain on the stack
707            unsafe { error::raise(guard, exception) }
708        }
709    }
710}
711
712unsafe extern "C-unwind" fn string_length(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
713    mrb_get_args!(mrb, none);
714    unwrap_interpreter!(mrb, to => guard);
715    let value = Value::from(slf);
716    let result = trampoline::length(&mut guard, value);
717    match result {
718        Ok(value) => value.inner(),
719        Err(exception) => {
720            // SAFETY: only Copy objects remain on the stack
721            unsafe { error::raise(guard, exception) }
722        }
723    }
724}
725
726unsafe extern "C-unwind" fn string_ord(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
727    mrb_get_args!(mrb, none);
728    unwrap_interpreter!(mrb, to => guard);
729    let value = Value::from(slf);
730    let result = trampoline::ord(&mut guard, value);
731    match result {
732        Ok(value) => value.inner(),
733        Err(exception) => {
734            // SAFETY: only Copy objects remain on the stack
735            unsafe { error::raise(guard, exception) }
736        }
737    }
738}
739
740unsafe extern "C-unwind" fn string_replace(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
741    let other = mrb_get_args!(mrb, required = 1);
742    unwrap_interpreter!(mrb, to => guard);
743    let value = Value::from(slf);
744    let other = Value::from(other);
745    let result = trampoline::replace(&mut guard, value, other);
746    match result {
747        Ok(value) => value.inner(),
748        Err(exception) => {
749            // SAFETY: only Copy objects remain on the stack
750            unsafe { error::raise(guard, exception) }
751        }
752    }
753}
754
755unsafe extern "C-unwind" fn string_reverse(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
756    mrb_get_args!(mrb, none);
757    unwrap_interpreter!(mrb, to => guard);
758    let value = Value::from(slf);
759    let result = trampoline::reverse(&mut guard, value);
760    match result {
761        Ok(value) => value.inner(),
762        Err(exception) => {
763            // SAFETY: only Copy objects remain on the stack
764            unsafe { error::raise(guard, exception) }
765        }
766    }
767}
768
769unsafe extern "C-unwind" fn string_reverse_bang(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
770    mrb_get_args!(mrb, none);
771    unwrap_interpreter!(mrb, to => guard);
772    let value = Value::from(slf);
773    let result = trampoline::reverse_bang(&mut guard, value);
774    match result {
775        Ok(value) => value.inner(),
776        Err(exception) => {
777            // SAFETY: only Copy objects remain on the stack
778            unsafe { error::raise(guard, exception) }
779        }
780    }
781}
782
783unsafe extern "C-unwind" fn string_rindex(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
784    let (needle, offset) = mrb_get_args!(mrb, required = 1, optional = 1);
785    unwrap_interpreter!(mrb, to => guard);
786    let value = Value::from(slf);
787    let needle = Value::from(needle);
788    let offset = offset.map(Value::from);
789    let result = trampoline::rindex(&mut guard, value, needle, offset);
790    match result {
791        Ok(value) => value.inner(),
792        Err(exception) => {
793            // SAFETY: only Copy objects remain on the stack
794            unsafe { error::raise(guard, exception) }
795        }
796    }
797}
798
799unsafe extern "C-unwind" fn string_scan(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
800    let (pattern, block) = mrb_get_args!(mrb, required = 1, &block);
801    unwrap_interpreter!(mrb, to => guard);
802    let value = Value::from(slf);
803    let pattern = Value::from(pattern);
804    let result = trampoline::scan(&mut guard, value, pattern, block);
805    match result {
806        Ok(result) => result.inner(),
807        Err(exception) => {
808            // SAFETY: only Copy objects remain on the stack
809            unsafe { error::raise(guard, exception) }
810        }
811    }
812}
813
814unsafe extern "C-unwind" fn string_setbyte(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
815    let (index, byte) = mrb_get_args!(mrb, required = 2);
816    unwrap_interpreter!(mrb, to => guard);
817    let value = Value::from(slf);
818    let index = Value::from(index);
819    let byte = Value::from(byte);
820    let result = trampoline::setbyte(&mut guard, value, index, byte);
821    match result {
822        Ok(value) => value.inner(),
823        Err(exception) => {
824            // SAFETY: only Copy objects remain on the stack
825            unsafe { error::raise(guard, exception) }
826        }
827    }
828}
829
830unsafe extern "C-unwind" fn string_slice_bang(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
831    mrb_get_args!(mrb, none);
832    unwrap_interpreter!(mrb, to => guard);
833    let value = Value::from(slf);
834    let result = trampoline::slice_bang(&mut guard, value);
835    match result {
836        Ok(value) => value.inner(),
837        Err(exception) => {
838            // SAFETY: only Copy objects remain on the stack
839            unsafe { error::raise(guard, exception) }
840        }
841    }
842}
843
844unsafe extern "C-unwind" fn string_split(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
845    mrb_get_args!(mrb, none);
846    unwrap_interpreter!(mrb, to => guard);
847    let value = Value::from(slf);
848    let result = trampoline::split(&mut guard, value);
849    match result {
850        Ok(value) => value.inner(),
851        Err(exception) => {
852            // SAFETY: only Copy objects remain on the stack
853            unsafe { error::raise(guard, exception) }
854        }
855    }
856}
857
858unsafe extern "C-unwind" fn string_start_with(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
859    let prefixes = mrb_get_args!(mrb, *args);
860    unwrap_interpreter!(mrb, to => guard);
861    let value = Value::from(slf);
862    let prefixes = prefixes.iter().map(|&other| Value::from(other));
863    let result = trampoline::start_with(&mut guard, value, prefixes);
864    match result {
865        Ok(result) => result.inner(),
866        Err(exception) => {
867            // SAFETY: only Copy objects remain on the stack
868            unsafe { error::raise(guard, exception) }
869        }
870    }
871}
872
873unsafe extern "C-unwind" fn string_swapcase(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
874    // FIXME: Support receiving case mapping options:
875    // <https://ruby-doc.org/core-3.1.2/doc/case_mapping_rdoc.html>
876    // <https://github.com/artichoke/artichoke/issues/2833>
877    mrb_get_args!(mrb, none);
878    unwrap_interpreter!(mrb, to => guard);
879    let value = Value::from(slf);
880    let result = trampoline::swapcase(&mut guard, value);
881    match result {
882        Ok(value) => value.inner(),
883        Err(exception) => {
884            // SAFETY: only Copy objects remain on the stack
885            unsafe { error::raise(guard, exception) }
886        }
887    }
888}
889
890unsafe extern "C-unwind" fn string_swapcase_bang(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
891    // FIXME: Support receiving case mapping options:
892    // <https://ruby-doc.org/core-3.1.2/doc/case_mapping_rdoc.html>
893    // <https://github.com/artichoke/artichoke/issues/2833>
894    mrb_get_args!(mrb, none);
895    unwrap_interpreter!(mrb, to => guard);
896    let value = Value::from(slf);
897    let result = trampoline::swapcase_bang(&mut guard, value);
898    match result {
899        Ok(value) => value.inner(),
900        Err(exception) => {
901            // SAFETY: only Copy objects remain on the stack
902            unsafe { error::raise(guard, exception) }
903        }
904    }
905}
906
907unsafe extern "C-unwind" fn string_to_f(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
908    mrb_get_args!(mrb, none);
909    unwrap_interpreter!(mrb, to => guard);
910    let value = Value::from(slf);
911    let result = trampoline::to_f(&mut guard, value);
912    match result {
913        Ok(value) => value.inner(),
914        Err(exception) => {
915            // SAFETY: only Copy objects remain on the stack
916            unsafe { error::raise(guard, exception) }
917        }
918    }
919}
920
921unsafe extern "C-unwind" fn string_to_i(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
922    let base = mrb_get_args!(mrb, optional = 1);
923    unwrap_interpreter!(mrb, to => guard);
924    let value = Value::from(slf);
925    let base = base.map(Value::from);
926    let result = trampoline::to_i(&mut guard, value, base);
927    match result {
928        Ok(value) => value.inner(),
929        Err(exception) => {
930            // SAFETY: only Copy objects remain on the stack
931            unsafe { error::raise(guard, exception) }
932        }
933    }
934}
935
936unsafe extern "C-unwind" fn string_to_s(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
937    mrb_get_args!(mrb, none);
938    unwrap_interpreter!(mrb, to => guard);
939    let value = Value::from(slf);
940    // TODO: dup `slf` when self is a subclass of `String`.
941    let result = trampoline::to_s(&mut guard, value);
942    match result {
943        Ok(value) => value.inner(),
944        Err(exception) => {
945            // SAFETY: only Copy objects remain on the stack
946            unsafe { error::raise(guard, exception) }
947        }
948    }
949}
950
951unsafe extern "C-unwind" fn string_upcase(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
952    // FIXME: Support receiving case mapping options:
953    // <https://ruby-doc.org/core-3.1.2/doc/case_mapping_rdoc.html>
954    // <https://github.com/artichoke/artichoke/issues/2833>
955    mrb_get_args!(mrb, none);
956    unwrap_interpreter!(mrb, to => guard);
957    let value = Value::from(slf);
958    let result = trampoline::upcase(&mut guard, value);
959    match result {
960        Ok(value) => value.inner(),
961        Err(exception) => {
962            // SAFETY: only Copy objects remain on the stack
963            unsafe { error::raise(guard, exception) }
964        }
965    }
966}
967
968unsafe extern "C-unwind" fn string_upcase_bang(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
969    // FIXME: Support receiving case mapping options:
970    // <https://ruby-doc.org/core-3.1.2/doc/case_mapping_rdoc.html>
971    // <https://github.com/artichoke/artichoke/issues/2833>
972    mrb_get_args!(mrb, none);
973    unwrap_interpreter!(mrb, to => guard);
974    let value = Value::from(slf);
975    let result = trampoline::upcase_bang(&mut guard, value);
976    match result {
977        Ok(value) => value.inner(),
978        Err(exception) => {
979            // SAFETY: only Copy objects remain on the stack
980            unsafe { error::raise(guard, exception) }
981        }
982    }
983}
984
985unsafe extern "C-unwind" fn string_valid_encoding(mrb: *mut sys::mrb_state, slf: sys::mrb_value) -> sys::mrb_value {
986    mrb_get_args!(mrb, none);
987    unwrap_interpreter!(mrb, to => guard);
988    let value = Value::from(slf);
989    let result = trampoline::is_valid_encoding(&mut guard, value);
990    match result {
991        Ok(value) => value.inner(),
992        Err(exception) => {
993            // SAFETY: only Copy objects remain on the stack
994            unsafe { error::raise(guard, exception) }
995        }
996    }
997}