#[repr(C)] pub struct BlobVec { pub data: *mut u8, pub len: usize, pub cap: usize, pub elem_size: usize, pub drop: Option, } #[no_mangle] extern "C" fn panic() -> ! { panic!("Called panic from external code."); } unsafe impl Send for BlobVec {} unsafe impl Sync for BlobVec {} unsafe extern "C" { unsafe fn vec_init(vec: *mut BlobVec, elem_size: usize, drop: Option); unsafe fn vec_push(vec: *mut BlobVec, elem: *const u8, size: usize); unsafe fn vec_pop(vec: *mut BlobVec); unsafe fn vec_get(vec: *mut BlobVec, index: usize) -> *mut u8; unsafe fn vec_remove(vec: *mut BlobVec, index: usize); unsafe fn vec_drop(vec: *mut BlobVec); unsafe fn exit(code: i32) -> !; } fn main() { static mut DROPS: usize = 1; let mut vec = BlobVec { data: core::ptr::null_mut(), len: 0, cap: 0, elem_size: 1, drop: None, }; fn as_slice(vec: &BlobVec) -> &[T] { assert_eq!(vec.elem_size, core::mem::size_of::()); unsafe { core::slice::from_raw_parts(vec.data as *const T, vec.len) } } extern "C" fn drop(ptr: *mut u8) { unsafe { DROPS *= ptr.cast::().read() as usize; } } unsafe { vec_init(&mut vec, 4, Some(drop)); let mut value: u32 = 2; assert_eq!(vec.len, 0); vec_push(&mut vec, &value as *const u32 as *const u8, 4); assert_eq!(vec.len, 1); assert_eq!(as_slice::(&vec), &[2]); let retrieved = *(vec_get(&mut vec, 0) as *mut u32); assert_eq!(retrieved, 2); assert_eq!(DROPS, 1); vec_pop(&mut vec); assert_eq!(vec.len, 0); assert_eq!(DROPS, 2); value = 3; vec_push(&mut vec, &value as *const u32 as *const u8, 4); assert_eq!(as_slice::(&vec), &[3]); value = 5; vec_push(&mut vec, &value as *const u32 as *const u8, 4); assert_eq!(as_slice::(&vec), &[3, 5]); assert_eq!(vec.len, 2); vec_pop(&mut vec); vec_pop(&mut vec); assert_eq!(DROPS, 2 * 3 * 5); eprintln!("Push/pop test passed\n"); } }