use std::alloc::Layout;
use std::ffi::c_void;
use std::ptr;
use crate::foreign::*;
use crate::r#impl::alloc;
macro_rules! foreign_copy_type {
($rust_type:ty, $foreign_type:ty) => {
impl FreeForeign for $rust_type {
type Foreign = $foreign_type;
unsafe fn free_foreign(ptr: *mut Self::Foreign) {
libc::free(ptr.cast::<c_void>());
}
}
impl CloneToForeign for $rust_type {
fn clone_to_foreign(&self) -> OwnedPointer<Self> {
let layout = Layout::new::<Self::Foreign>();
unsafe {
let p = alloc::<Self::Foreign>(layout);
*p = *self as Self::Foreign;
OwnedPointer::new(p)
}
}
}
impl FromForeign for $rust_type {
unsafe fn cloned_from_foreign(p: *const Self::Foreign) -> Self {
*p
}
}
impl BorrowForeign for $rust_type {
type Storage<'a> = &'a Self;
fn borrow_foreign(&self) -> BorrowedPointer<Self, Self::Storage<'_>> {
unsafe { BorrowedPointer::new_borrowed(self, |raw| raw) }
}
}
impl BorrowForeignMut for $rust_type {
type Storage<'a> = BorrowedStorage<'a, Self>;
fn borrow_foreign_mut(&mut self) -> BorrowedMutPointer<Self, Self::Storage<'_>> {
unsafe { BorrowedMutPointer::new_borrowed(self, |raw| raw) }
}
}
#[allow(clippy::undocumented_unsafe_blocks)]
unsafe impl FixedAlloc for $rust_type {
unsafe fn clone_into_foreign(dest: *mut Self::Foreign, src: &Self) {
ptr::write(dest, *src)
}
unsafe fn clone_from_native_slice(dest: *mut Self::Foreign, src: &[Self]) {
unsafe {
ptr::copy_nonoverlapping(src.as_ptr().cast::<Self::Foreign>(), dest, src.len());
}
}
}
};
}
foreign_copy_type!(bool, bool);
foreign_copy_type!(i8, i8);
foreign_copy_type!(u8, u8);
foreign_copy_type!(i16, i16);
foreign_copy_type!(u16, u16);
foreign_copy_type!(i32, i32);
foreign_copy_type!(u32, u32);
foreign_copy_type!(i64, i64);
foreign_copy_type!(u64, u64);
foreign_copy_type!(isize, libc::ptrdiff_t);
foreign_copy_type!(usize, libc::size_t);
foreign_copy_type!(f32, f32);
foreign_copy_type!(f64, f64);
#[allow(clippy::undocumented_unsafe_blocks)]
#[cfg(test)]
mod tests {
use std::ptr;
use crate::foreign::*;
#[test]
fn test_foreign_int_convert() {
let i = 123i8;
let p = i.clone_to_foreign();
unsafe {
assert_eq!(i, *p.as_ptr());
assert_eq!(i, i8::cloned_from_foreign(p.as_ptr()));
}
assert_eq!(i, p.into_native());
let p = i.clone_to_foreign();
unsafe {
assert_eq!(i, i8::from_foreign(p.into_inner()));
}
}
#[test]
fn test_foreign_int_borrow() {
let i = 123i8;
unsafe {
assert_eq!(i, *i.borrow_foreign().as_ptr());
}
assert_eq!(i, 123i8);
}
#[test]
fn test_foreign_int_borrow_clone_to_foreign() {
let i = 123i8;
let cloned = i.borrow_foreign().clone_to_foreign();
assert_ne!(cloned.as_ptr(), ptr::addr_of!(i));
unsafe { assert_eq!(*cloned.as_ptr(), 123i8) };
}
#[test]
fn test_foreign_int_borrow_mut_clone_to_foreign() {
let mut j = 123i8;
let mut borrowed = j.borrow_foreign_mut();
unsafe { *borrowed.as_mut_ptr() = 45i8 };
let cloned = borrowed.clone_to_foreign();
unsafe { assert_eq!(*cloned.as_ptr(), 45i8) };
}
#[test]
fn test_foreign_int_borrow_mut() {
let mut i = 123i8;
let mut borrowed = i.borrow_foreign_mut();
unsafe {
assert_eq!(*borrowed.as_ptr(), 123i8);
*borrowed.as_mut_ptr() = 45i8;
}
let borrowed = i.borrow_foreign_mut();
unsafe {
assert_eq!(*borrowed.as_ptr(), 45i8);
}
assert_eq!(i, 45i8);
}
}