use crate::vm::value::Value; use std::alloc::{Layout, alloc}; #[repr(C)] pub struct Object { header: ObjectHeader, fields: [Value], } pub struct ObjectHeader { field_count: usize, } fn get_object(field_count: usize) -> Box { let (layout, fields_base) = Layout::array::(field_count) .and_then(|fields_array_layout| Layout::new::().extend(fields_array_layout)) .unwrap(); println!("{:?}", layout); let ptr = unsafe { alloc(layout) }; if ptr.is_null() { panic!("failed to allocate memory"); } unsafe { ptr.cast::() .write(ObjectHeader { field_count }); let fields_ptr = ptr.add(fields_base).cast::(); // initialize each field to Value::Null for i in 0..field_count { fields_ptr.add(i).write(Value::Null); } // this is somehow magic // https://stackoverflow.com/questions/64120001/how-to-create-a-smart-pointer-to-an-unsized-type-with-an-embedded-slice Box::from_raw(std::ptr::slice_from_raw_parts(ptr as *mut Value, field_count) as *mut Object) } } #[cfg(test)] mod tests { use super::*; #[test] fn melt_the_processor() { let mut o = get_object(3); assert_eq!(o.header.field_count, 3); assert_eq!(o.fields.len(), 3); o.fields.fill(Value::Int(42)); assert!(o.fields.iter().all(|v| *v == Value::Int(42))); } }