Skip to main content

intuicio_core/
utils.rs

1//! Helpers for moving [`Object`] values on and off a data stack.
2use crate::{object::Object, registry::Registry, types::TypeQuery};
3use intuicio_data::{data_stack::DataStack, non_zero_dealloc};
4
5/// Moves an object onto the stack as a plain value of its type.
6///
7/// The object's own allocation is freed, since the stack takes the bytes.
8/// Returns `false` when the value does not fit.
9///
10/// **Native types only.** A stack slot keeps its destructor as a plain function
11/// pointer. A runtime type drops itself by a field walk, which is not a
12/// function pointer. Such a value would be dropped without its fields, and
13/// every allocation they own would leak, so this refuses instead. Put a runtime
14/// value in a `DynamicManaged` and push that.
15pub fn object_push_to_stack(object: Object, data_stack: &mut DataStack) -> bool {
16    unsafe {
17        let (handle, memory) = object.into_inner();
18        if memory.is_null() {
19            return false;
20        }
21        let Some(finalizer) = handle.finalizer().as_native() else {
22            return false;
23        };
24        let bytes = std::slice::from_raw_parts(memory, handle.layout().size());
25        let result = data_stack.push_raw(*handle.layout(), handle.type_hash(), finalizer, bytes);
26        non_zero_dealloc(memory, *handle.layout());
27        result
28    }
29}
30
31/// Moves the top stack value into an [`Object`], looking its type up in the
32/// registry.
33///
34/// Puts the value back and returns [`None`] when the type is not registered.
35pub fn object_pop_from_stack(data_stack: &mut DataStack, registry: &Registry) -> Option<Object> {
36    unsafe {
37        let (layout, type_hash, finalizer, data) = data_stack.pop_raw()?;
38        if let Some(handle) = registry.find_type(TypeQuery {
39            type_hash: Some(type_hash),
40            ..Default::default()
41        }) {
42            Object::from_bytes(handle, &data)
43        } else {
44            data_stack.push_raw(layout, type_hash, finalizer, &data);
45            None
46        }
47    }
48}