use std::convert::TryFrom;
use std::mem;
use std::os::raw::c_void;
use std::vec::Vec;
use crate::errors::{null_pointer, StdResult};
#[repr(C)]
pub struct Region {
pub offset: u32,
pub capacity: u32,
pub length: u32,
}
pub fn alloc(size: usize) -> *mut c_void {
let data: Vec<u8> = Vec::with_capacity(size);
let data_ptr = data.as_ptr() as usize;
let region = build_region_from_components(
u32::try_from(data_ptr).expect("pointer doesn't fit in u32"),
u32::try_from(data.capacity()).expect("capacity doesn't fit in u32"),
0,
);
mem::forget(data);
Box::into_raw(region) as *mut c_void
}
pub fn release_buffer(buffer: Vec<u8>) -> *mut c_void {
let region = build_region(&buffer);
mem::forget(buffer);
Box::into_raw(region) as *mut c_void
}
pub unsafe fn consume_region(ptr: *mut c_void) -> StdResult<Vec<u8>> {
if ptr.is_null() {
return Err(null_pointer());
}
let region = Box::from_raw(ptr as *mut Region);
let buffer = Vec::from_raw_parts(
region.offset as *mut u8,
region.length as usize,
region.capacity as usize,
);
Ok(buffer)
}
pub fn build_region(data: &[u8]) -> Box<Region> {
let data_ptr = data.as_ptr() as usize;
build_region_from_components(
u32::try_from(data_ptr).expect("pointer doesn't fit in u32"),
u32::try_from(data.len()).expect("length doesn't fit in u32"),
u32::try_from(data.len()).expect("length doesn't fit in u32"),
)
}
fn build_region_from_components(offset: u32, capacity: u32, length: u32) -> Box<Region> {
Box::new(Region {
offset: offset,
capacity: capacity,
length: length,
})
}