artichoke_backend/extn/core/array/
ffi.rsuse std::ptr::NonNull;
use std::slice;
use crate::extn::core::array::{Array, RawParts};
use crate::extn::prelude::*;
#[no_mangle]
unsafe extern "C" fn mrb_ary_new(mrb: *mut sys::mrb_state) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let result = Array::new();
let result = Array::alloc_value(result, &mut guard);
match result {
Ok(value) => value.inner(),
Err(exception) => error::raise(guard, exception),
}
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_new_capa(mrb: *mut sys::mrb_state, capa: sys::mrb_int) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let capacity = usize::try_from(capa).unwrap_or_default();
let result = Array::with_capacity(capacity);
let result = Array::alloc_value(result, &mut guard);
match result {
Ok(value) => value.inner(),
Err(exception) => error::raise(guard, exception),
}
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_new_from_values(
mrb: *mut sys::mrb_state,
size: sys::mrb_int,
vals: *const sys::mrb_value,
) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let size = usize::try_from(size).unwrap_or_default();
let values = slice::from_raw_parts(vals, size);
let result = Array::from(values);
let result = Array::alloc_value(result, &mut guard);
match result {
Ok(value) => {
let basic = sys::mrb_sys_basic_ptr(value.inner());
sys::mrb_write_barrier(mrb, basic);
value.inner()
}
Err(exception) => error::raise(guard, exception),
}
}
#[no_mangle]
unsafe extern "C" fn mrb_assoc_new(
mrb: *mut sys::mrb_state,
one: sys::mrb_value,
two: sys::mrb_value,
) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let result = Array::assoc(one.into(), two.into());
let result = Array::alloc_value(result, &mut guard);
match result {
Ok(value) => {
let basic = sys::mrb_sys_basic_ptr(value.inner());
sys::mrb_write_barrier(mrb, basic);
value.inner()
}
Err(exception) => error::raise(guard, exception),
}
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_splat(mrb: *mut sys::mrb_state, value: sys::mrb_value) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let mut value = Value::from(value);
let result = if Array::unbox_from_value(&mut value, &mut guard).is_ok() {
Ok(value)
} else {
let mut result = Array::with_capacity(1);
result.push(value);
Array::alloc_value(result, &mut guard)
};
match result {
Ok(value) => {
let basic = sys::mrb_sys_basic_ptr(value.inner());
sys::mrb_write_barrier(mrb, basic);
value.inner()
}
Err(exception) => error::raise(guard, exception),
}
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_concat(mrb: *mut sys::mrb_state, ary: sys::mrb_value, other: sys::mrb_value) {
unwrap_interpreter!(mrb, to => guard, or_else = ());
let mut array = Value::from(ary);
let mut other = Value::from(other);
if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
if let Ok(other) = Array::unbox_from_value(&mut other, &mut guard) {
let array_mut = array.as_inner_mut();
array_mut.extend(other.iter());
let inner = array.take();
Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
} else {
emit_fatal_warning!(
"ffi: mrb_ary_concat: Expected {:?} argument but got {:?} argument",
Ruby::Array,
other.ruby_type()
);
}
let basic = sys::mrb_sys_basic_ptr(ary);
sys::mrb_write_barrier(mrb, basic);
}
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_pop(mrb: *mut sys::mrb_state, ary: sys::mrb_value) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let mut array = Value::from(ary);
let result = if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
let array_mut = array.as_inner_mut();
let popped = array_mut.pop();
let inner = array.take();
Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
guard.convert(popped)
} else {
Value::nil()
};
let basic = sys::mrb_sys_basic_ptr(ary);
sys::mrb_write_barrier(mrb, basic);
result.inner()
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_push(mrb: *mut sys::mrb_state, ary: sys::mrb_value, value: sys::mrb_value) {
unwrap_interpreter!(mrb, to => guard, or_else = ());
let mut array = Value::from(ary);
let value = Value::from(value);
if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
let array_mut = array.as_inner_mut();
array_mut.push(value);
let inner = array.take();
Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
}
let basic = sys::mrb_sys_basic_ptr(ary);
sys::mrb_write_barrier(mrb, basic);
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_ref(
mrb: *mut sys::mrb_state,
ary: sys::mrb_value,
offset: sys::mrb_int,
) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let mut ary = Value::from(ary);
let offset = usize::try_from(offset).unwrap_or_default();
let result = if let Ok(array) = Array::unbox_from_value(&mut ary, &mut guard) {
guard.convert(array.get(offset))
} else {
Value::nil()
};
result.inner()
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_set(
mrb: *mut sys::mrb_state,
ary: sys::mrb_value,
offset: sys::mrb_int,
value: sys::mrb_value,
) {
unwrap_interpreter!(mrb, to => guard, or_else = ());
let mut array = Value::from(ary);
let value = Value::from(value);
if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
let offset = aref::offset_to_index(offset, array.len()).unwrap_or(0);
if Value::from(ary) != value {
let array_mut = array.as_inner_mut();
array_mut.set(offset, value);
let inner = array.take();
Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
}
}
let basic = sys::mrb_sys_basic_ptr(ary);
sys::mrb_write_barrier(mrb, basic);
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_shift(mrb: *mut sys::mrb_state, ary: sys::mrb_value) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let mut array = Value::from(ary);
let result = if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
let array_mut = array.as_inner_mut();
let result = array_mut.shift();
let inner = array.take();
Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
guard.convert(result)
} else {
Value::nil()
};
let basic = sys::mrb_sys_basic_ptr(ary);
sys::mrb_write_barrier(mrb, basic);
result.inner()
}
#[no_mangle]
unsafe extern "C" fn mrb_ary_unshift(
mrb: *mut sys::mrb_state,
ary: sys::mrb_value,
value: sys::mrb_value,
) -> sys::mrb_value {
unwrap_interpreter!(mrb, to => guard);
let mut array = Value::from(ary);
if let Ok(mut array) = Array::unbox_from_value(&mut array, &mut guard) {
let array_mut = array.as_inner_mut();
array_mut.unshift(value.into());
let inner = array.take();
Array::box_into_value(inner, ary.into(), &mut guard).expect("Array reboxing should not fail");
}
let basic = sys::mrb_sys_basic_ptr(ary);
sys::mrb_write_barrier(mrb, basic);
value
}
#[no_mangle]
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_sign_loss)]
unsafe extern "C" fn mrb_ary_artichoke_free(mrb: *mut sys::mrb_state, ary: *mut sys::RArray) {
let _ = mrb;
let Some(mut ptr) = NonNull::new((*ary).as_.heap.ptr) else {
return;
};
let length = (*ary).as_.heap.len as usize;
let capacity = (*ary).as_.heap.aux.capa as usize;
drop(Array::from_raw_parts(RawParts {
ptr: ptr.as_mut(),
length,
capacity,
}));
}