76 lines
2.2 KiB
Rust
76 lines
2.2 KiB
Rust
#[repr(C)]
|
|
pub struct BlobVec {
|
|
pub data: *mut u8,
|
|
pub len: usize,
|
|
pub cap: usize,
|
|
pub elem_size: usize,
|
|
pub drop: Option<extern "C" fn(*mut u8)>,
|
|
}
|
|
|
|
#[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<extern "C" fn(*mut u8)>);
|
|
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<T>(vec: &BlobVec) -> &[T] {
|
|
assert_eq!(vec.elem_size, core::mem::size_of::<T>());
|
|
unsafe { core::slice::from_raw_parts(vec.data as *const T, vec.len) }
|
|
}
|
|
|
|
extern "C" fn drop(ptr: *mut u8) {
|
|
unsafe {
|
|
DROPS *= ptr.cast::<u32>().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::<u32>(&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::<u32>(&vec), &[3]);
|
|
value = 5;
|
|
vec_push(&mut vec, &value as *const u32 as *const u8, 4);
|
|
assert_eq!(as_slice::<u32>(&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");
|
|
}
|
|
}
|