artichoke_backend/extn/core/array/
ffi.rs1use std::ptr::NonNull;
2use std::slice;
3
4use crate::extn::core::array::{Array, RawParts};
5use crate::extn::prelude::*;
6
7#[unsafe(no_mangle)]
11unsafe extern "C-unwind" fn mrb_ary_new(mrb: *mut sys::mrb_state) -> sys::mrb_value {
12 unwrap_interpreter!(mrb, to => guard);
13 let result = Array::new();
14 let result = Array::alloc_value(result, &mut guard);
15 match result {
16 Ok(value) => value.inner(),
17 Err(exception) => {
18 unsafe { error::raise(guard, exception) }
20 }
21 }
22}
23
24#[unsafe(no_mangle)]
28unsafe extern "C-unwind" fn mrb_ary_new_capa(mrb: *mut sys::mrb_state, capa: sys::mrb_int) -> sys::mrb_value {
29 unwrap_interpreter!(mrb, to => guard);
30 let capacity = usize::try_from(capa).unwrap_or_default();
31 let result = Array::with_capacity(capacity);
32 let result = Array::alloc_value(result, &mut guard);
33 match result {
34 Ok(value) => value.inner(),
35 Err(exception) => {
36 unsafe { error::raise(guard, exception) }
38 }
39 }
40}
41
42#[unsafe(no_mangle)]
46unsafe extern "C-unwind" fn mrb_ary_new_from_values(
47 mrb: *mut sys::mrb_state,
48 size: sys::mrb_int,
49 vals: *const sys::mrb_value,
50) -> sys::mrb_value {
51 unwrap_interpreter!(mrb, to => guard);
52 let size = usize::try_from(size).unwrap_or_default();
53 let values = slice::from_raw_parts(vals, size);
54 let result = Array::from(values);
55 let result = Array::alloc_value(result, &mut guard);
56 match result {
57 Ok(value) => {
58 let basic = sys::mrb_sys_basic_ptr(value.inner());
59 sys::mrb_write_barrier(mrb, basic);
60 value.inner()
61 }
62 Err(exception) => {
63 unsafe { error::raise(guard, exception) }
65 }
66 }
67}
68
69#[unsafe(no_mangle)]
73unsafe extern "C-unwind" fn mrb_assoc_new(
74 mrb: *mut sys::mrb_state,
75 one: sys::mrb_value,
76 two: sys::mrb_value,
77) -> sys::mrb_value {
78 unwrap_interpreter!(mrb, to => guard);
79 let result = Array::assoc(one.into(), two.into());
80 let result = Array::alloc_value(result, &mut guard);
81 match result {
82 Ok(value) => {
83 let basic = sys::mrb_sys_basic_ptr(value.inner());
84 sys::mrb_write_barrier(mrb, basic);
85 value.inner()
86 }
87 Err(exception) => {
88 unsafe { error::raise(guard, exception) }
90 }
91 }
92}
93
94#[unsafe(no_mangle)]
98unsafe extern "C-unwind" fn mrb_ary_splat(mrb: *mut sys::mrb_state, value: sys::mrb_value) -> sys::mrb_value {
99 unwrap_interpreter!(mrb, to => guard);
100 let mut value = Value::from(value);
101 let result = if Array::unbox_from_value(&mut value, &mut guard).is_ok() {
102 Ok(value)
103 } else {
104 let mut result = Array::with_capacity(1);
105 result.push(value);
106 Array::alloc_value(result, &mut guard)
107 };
108 match result {
109 Ok(value) => {
110 let basic = sys::mrb_sys_basic_ptr(value.inner());
111 sys::mrb_write_barrier(mrb, basic);
112 value.inner()
113 }
114 Err(exception) => {
115 unsafe { error::raise(guard, exception) }
117 }
118 }
119}
120
121#[unsafe(no_mangle)]
127unsafe extern "C-unwind" fn mrb_ary_concat(mrb: *mut sys::mrb_state, ary: sys::mrb_value, other: sys::mrb_value) {
128 unwrap_interpreter!(mrb, to => guard, or_else = ());
129 let mut array = Value::from(ary);
130 let mut other = Value::from(other);
131 if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
132 if let Ok(other) = Array::unbox_from_value(&mut other, &mut guard) {
133 let array_mut = array.as_inner_mut();
136 array_mut.extend(other.iter());
137
138 let inner = array.take();
139 Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
140 } else {
141 emit_fatal_warning!(
142 "ffi: mrb_ary_concat: Expected {:?} argument but got {:?} argument",
143 Ruby::Array,
144 other.ruby_type()
145 );
146 }
147
148 let basic = sys::mrb_sys_basic_ptr(ary);
149 sys::mrb_write_barrier(mrb, basic);
150 }
151}
152
153#[unsafe(no_mangle)]
157unsafe extern "C-unwind" fn mrb_ary_pop(mrb: *mut sys::mrb_state, ary: sys::mrb_value) -> sys::mrb_value {
158 unwrap_interpreter!(mrb, to => guard);
159 let mut array = Value::from(ary);
160 let result = if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
161 let array_mut = array.as_inner_mut();
164 let popped = array_mut.pop();
165
166 let inner = array.take();
167 Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
168
169 guard.convert(popped)
170 } else {
171 Value::nil()
172 };
173 let basic = sys::mrb_sys_basic_ptr(ary);
174 sys::mrb_write_barrier(mrb, basic);
175 result.inner()
176}
177
178#[unsafe(no_mangle)]
182unsafe extern "C-unwind" fn mrb_ary_push(mrb: *mut sys::mrb_state, ary: sys::mrb_value, value: sys::mrb_value) {
183 unwrap_interpreter!(mrb, to => guard, or_else = ());
184 let mut array = Value::from(ary);
185 let value = Value::from(value);
186 if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
187 let array_mut = array.as_inner_mut();
190 array_mut.push(value);
191
192 let inner = array.take();
193 Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
194 }
195 let basic = sys::mrb_sys_basic_ptr(ary);
196 sys::mrb_write_barrier(mrb, basic);
197}
198
199#[unsafe(no_mangle)]
203unsafe extern "C-unwind" fn mrb_ary_ref(
204 mrb: *mut sys::mrb_state,
205 ary: sys::mrb_value,
206 offset: sys::mrb_int,
207) -> sys::mrb_value {
208 unwrap_interpreter!(mrb, to => guard);
209 let mut ary = Value::from(ary);
210 let offset = usize::try_from(offset).unwrap_or_default();
211 let result = if let Ok(array) = Array::unbox_from_value(&mut ary, &mut guard) {
212 guard.convert(array.get(offset))
213 } else {
214 Value::nil()
215 };
216 result.inner()
217}
218
219#[unsafe(no_mangle)]
223unsafe extern "C-unwind" fn mrb_ary_set(
224 mrb: *mut sys::mrb_state,
225 ary: sys::mrb_value,
226 offset: sys::mrb_int,
227 value: sys::mrb_value,
228) {
229 unwrap_interpreter!(mrb, to => guard, or_else = ());
230 let mut array = Value::from(ary);
231 let value = Value::from(value);
232 if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
233 let offset = aref::offset_to_index(offset, array.len()).unwrap_or(0);
234 if Value::from(ary) != value {
236 let array_mut = array.as_inner_mut();
239 array_mut.set(offset, value);
240
241 let inner = array.take();
242 Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
243 }
244 }
245 let basic = sys::mrb_sys_basic_ptr(ary);
246 sys::mrb_write_barrier(mrb, basic);
247}
248
249#[unsafe(no_mangle)]
253unsafe extern "C-unwind" fn mrb_ary_shift(mrb: *mut sys::mrb_state, ary: sys::mrb_value) -> sys::mrb_value {
254 unwrap_interpreter!(mrb, to => guard);
255 let mut array = Value::from(ary);
256 let result = if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
257 let array_mut = array.as_inner_mut();
260 let result = array_mut.shift();
261
262 let inner = array.take();
263 Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
264
265 guard.convert(result)
266 } else {
267 Value::nil()
268 };
269 let basic = sys::mrb_sys_basic_ptr(ary);
270 sys::mrb_write_barrier(mrb, basic);
271 result.inner()
272}
273
274#[unsafe(no_mangle)]
278unsafe extern "C-unwind" fn mrb_ary_unshift(
279 mrb: *mut sys::mrb_state,
280 ary: sys::mrb_value,
281 value: sys::mrb_value,
282) -> sys::mrb_value {
283 unwrap_interpreter!(mrb, to => guard);
284 let mut array = Value::from(ary);
285 if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
286 let array_mut = array.as_inner_mut();
289 array_mut.unshift(value.into());
290
291 let inner = array.take();
292 Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
293 }
294 let basic = sys::mrb_sys_basic_ptr(ary);
295 sys::mrb_write_barrier(mrb, basic);
296 value
297}
298
299#[unsafe(no_mangle)]
300#[expect(
301 clippy::cast_possible_truncation,
302 clippy::cast_sign_loss,
303 reason = "mruby stores sizes as int64_t instead of size_t"
304)]
305unsafe extern "C-unwind" fn mrb_ary_artichoke_free(mrb: *mut sys::mrb_state, ary: *mut sys::RArray) {
306 let _ = mrb;
307
308 let Some(mut ptr) = NonNull::new((*ary).as_.heap.ptr) else {
309 return;
312 };
313 let length = (*ary).as_.heap.len as usize;
314 let capacity = (*ary).as_.heap.aux.capa as usize;
315
316 drop(Array::from_raw_parts(RawParts {
317 ptr: ptr.as_mut(),
318 length,
319 capacity,
320 }));
321}