Skip to main content

nifty_rt/abi/
structs.rs

1//! Structs: building, reading fields, and changing them in place.
2
3use std::rc::Rc;
4use std::slice;
5
6use crate::value::{self, Slot, StructObject, TypeDesc};
7
8/// A struct of type `ty` whose fields are taken, in order, from `fields`.
9///
10/// # Safety
11/// `ty` is a struct type and `fields` points to one slot per field, of the field's type.
12#[unsafe(no_mangle)]
13pub(crate) unsafe extern "C" fn nf_struct_new(ty: &'static TypeDesc, fields: *const Slot) -> Slot {
14    let len = ty.children().len();
15    let fields = if len == 0 {
16        Box::default()
17    } else {
18        // SAFETY: by the caller's contract.
19        unsafe { slice::from_raw_parts(fields, len) }.into()
20    };
21    value::into_slot(Rc::new(StructObject { ty, fields }))
22}
23
24/// The field at `index` of the borrowed struct, borrowed from it.
25#[unsafe(no_mangle)]
26pub(crate) extern "C" fn nf_struct_get(object: Slot, index: usize) -> Slot {
27    value::as_struct(object).fields[index]
28}
29
30/// The slot of the field at `index` in the struct in `place`, which becomes its only
31/// owner's so the field can be changed. The slot is valid until the struct next changes.
32///
33/// # Safety
34/// `place` holds a struct with a field at `index`.
35#[unsafe(no_mangle)]
36pub(crate) unsafe extern "C" fn nf_struct_field_mut(place: *mut Slot, index: usize) -> *mut Slot {
37    // SAFETY: by the caller's contract.
38    &raw mut value::struct_mut(unsafe { &mut *place }).fields[index]
39}