use std::alloc::{handle_alloc_error, Layout};
mod r#box;
mod cow;
mod option;
mod primitive;
mod slice;
mod string;
mod vec;
pub(crate) fn alloc<T>(layout: Layout) -> *mut T {
let p = unsafe { libc::aligned_alloc(layout.align(), layout.size()).cast::<T>() };
if p.is_null() {
handle_alloc_error(layout);
}
p
}
#[cfg(test)]
mod tests {
use crate::foreign::*;
use std::ffi::{c_char, CStr, CString};
use std::marker::PhantomData;
pub struct PointerWithLifetime<'a>(*const c_char, PhantomData<&'a CStr>);
impl FreeForeign for PointerWithLifetime<'_> {
type Foreign = *const c_char;
unsafe fn free_foreign(_ptr: *mut Self::Foreign) {
panic!("should not be reached");
}
}
impl<'a> PointerWithLifetime<'a> {
fn new(bp: &BorrowedPointer<CStr, &'a CStr>) -> Self {
PointerWithLifetime(bp.as_ptr(), PhantomData)
}
fn as_ptr(&self) -> *const *const c_char {
&self.0
}
}
impl<'a> BorrowForeign<'a> for PointerWithLifetime<'a> {
type Storage = &'a Self;
fn borrow_foreign(&'a self) -> BorrowedPointer<Self, &'a Self> {
unsafe { BorrowedPointer::new(&self.0, self) }
}
}
impl<'a> BorrowForeignMut<'a> for PointerWithLifetime<'a> {
type Storage = &'a mut Self;
fn borrow_foreign_mut(&'a mut self) -> BorrowedMutPointer<Self, &'a mut Self> {
unsafe { BorrowedMutPointer::new(&mut self.0, self) }
}
}
#[test]
fn test_borrow_struct() {
let s = CString::new("hello world").unwrap();
let mut st = PointerWithLifetime::new(&s.borrow_foreign());
let b = st.borrow_foreign();
let p = st.as_ptr();
assert_eq!(b.as_ptr(), p);
assert_eq!(st.borrow_foreign_mut().as_ptr(), p);
}
#[test]
fn test_borrow_box() {
let s = CString::new("hello world").unwrap();
let st = PointerWithLifetime::new(&s.borrow_foreign());
let mut st = Box::new(st);
let b = st.borrow_foreign();
let p = st.as_ptr();
assert_eq!(b.as_ptr(), p);
assert_eq!(st.borrow_foreign_mut().as_ptr(), p);
}
}