use std::convert::TryFrom;
use std::mem;
use std::vec::Vec;
#[repr(C)]
pub struct Region {
pub offset: u32,
pub capacity: u32,
pub length: u32,
}
pub fn alloc(size: usize) -> *mut Region {
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)
}
pub fn release_buffer(buffer: Vec<u8>) -> *mut Region {
let region = build_region(&buffer);
mem::forget(buffer);
Box::into_raw(region)
}
pub unsafe fn consume_region(ptr: *mut Region) -> Vec<u8> {
assert!(!ptr.is_null(), "Region pointer is null");
let region = Box::from_raw(ptr);
let region_start = region.offset as *mut u8;
assert!(!region_start.is_null(), "Region starts at null pointer");
Vec::from_raw_parts(
region_start,
region.length as usize,
region.capacity as usize,
)
}
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,
capacity,
length,
})
}
#[cfg(feature = "iterator")]
pub fn get_optional_region_address(region: &Option<&Box<Region>>) -> u32 {
fn get_region_address(region: &Box<Region>) -> u32 {
region.as_ref() as *const Region as u32
}
region.map(get_region_address).unwrap_or(0)
}