use crate::foreign::*;
impl<T> FreeForeign for Vec<T>
where
[T]: FreeForeign,
{
type Foreign = <[T] as FreeForeign>::Foreign;
unsafe fn free_foreign(x: *mut Self::Foreign) {
<[T]>::free_foreign(x)
}
}
impl<T> CloneToForeign for Vec<T>
where
[T]: CloneToForeign,
{
fn clone_to_foreign(&self) -> OwnedPointer<Self> {
(**self).clone_to_foreign().into()
}
}
impl<T> BorrowForeign for Vec<T>
where
[T]: BorrowForeign,
{
type Storage<'a>
= <[T] as BorrowForeign>::Storage<'a>
where
Self: 'a;
fn borrow_foreign(&self) -> BorrowedPointer<Self, Self::Storage<'_>> {
(**self).borrow_foreign().into()
}
}
impl<T> IntoForeign for Vec<T>
where
[T]: BorrowForeignMut,
{
type Storage = Self;
fn into_foreign(mut self) -> BorrowedMutPointer<Self, Self> {
let p = self.borrow_foreign_mut().as_mut_ptr();
unsafe { BorrowedMutPointer::new(p, self) }
}
}
impl<T> BorrowForeignMut for Vec<T>
where
[T]: BorrowForeignMut,
{
type Storage<'a>
= <[T] as BorrowForeignMut>::Storage<'a>
where
Self: 'a;
fn borrow_foreign_mut(&mut self) -> BorrowedMutPointer<Self, Self::Storage<'_>> {
(**self).borrow_foreign_mut().into()
}
}
#[allow(clippy::undocumented_unsafe_blocks)]
#[cfg(test)]
mod tests {
use std::ffi::c_void;
use std::ptr;
use crate::foreign::*;
use crate::r#impl::tests::PrimitiveWithLifetime;
#[test]
fn test_vec() {
let v: Vec<u8> = vec![1, 2, 3];
let bstr = b"\x01\x02\x03";
let cloned = v.clone_to_foreign();
unsafe {
assert_eq!(
libc::memcmp(
cloned.as_ptr().cast::<c_void>(),
bstr.as_ptr().cast::<c_void>(),
bstr.len()
),
0
);
}
}
#[test]
fn test_vec_borrow() {
let v: Vec<u8> = vec![0x31, 0x41, 0x59];
let bstr = b"\x31\x41\x59";
let borrowed = v.borrow_foreign();
unsafe {
assert_eq!(
libc::memcmp(
borrowed.as_ptr().cast::<c_void>(),
bstr.as_ptr().cast::<c_void>(),
bstr.len()
),
0
);
}
}
#[test]
fn test_vec_borrow_clone_to_foreign() {
let v: Vec<u8> = vec![1, 2, 3];
let p = v.borrow_foreign().clone_to_foreign_ptr();
unsafe {
assert_eq!(
libc::memcmp(p.cast::<c_void>(), v.as_ptr().cast::<c_void>(), 3),
0
);
assert_ne!(p.cast_const(), v.as_ptr());
libc::free(p.cast::<c_void>());
}
}
#[test]
fn test_vec_borrow_mut_write() {
let mut v: Vec<u8> = vec![1, 2, 3];
let mut borrowed = v.borrow_foreign_mut();
unsafe {
ptr::write(borrowed.as_mut_ptr().offset(1), 0xFF);
assert_eq!(*(borrowed.as_ptr().offset(1)), 0xFF);
}
let cloned = borrowed.clone_to_foreign();
unsafe {
assert_eq!(*cloned.as_ptr(), 1);
assert_eq!(*cloned.as_ptr().offset(1), 0xFF);
assert_eq!(*cloned.as_ptr().offset(2), 3);
}
}
#[test]
fn test_vec_into_foreign_write() {
let v: Vec<u8> = vec![1, 2, 3];
let mut consumed = v.into_foreign();
unsafe {
ptr::write(consumed.as_mut_ptr().offset(1), 0xFF);
assert_eq!(*consumed.as_ptr().offset(1), 0xFF);
}
let cloned = consumed.clone_to_foreign();
unsafe { assert_eq!(*cloned.as_ptr().offset(1), 0xFF) };
}
#[test]
fn test_vec_into_foreign() {
let v: Vec<u8> = vec![0x21, 0x78, 0x28];
let bstr = b"\x21\x78\x28";
let consumed = v.into_foreign();
unsafe {
assert_eq!(
libc::memcmp(
consumed.as_ptr().cast::<c_void>(),
bstr.as_ptr().cast::<c_void>(),
bstr.len()
),
0
);
}
}
#[test]
fn test_vec_into_foreign_with_lifetime() {
let n = 7u8;
let v: Vec<PrimitiveWithLifetime> = vec![PrimitiveWithLifetime::new(&n)];
let consumed = v.into_foreign();
unsafe { assert_eq!((*consumed.as_ptr()).0, 7) };
}
#[test]
fn test_vec_into_foreign_clone_to_foreign() {
let v: Vec<u8> = vec![1, 2, 3];
let consumed = v.into_foreign();
let cloned = consumed.clone_to_foreign();
assert_ne!(cloned.as_ptr(), consumed.as_ptr());
unsafe {
assert_eq!(
libc::memcmp(
cloned.as_ptr().cast::<c_void>(),
consumed.as_ptr().cast::<c_void>(),
3
),
0
);
}
}
#[test]
fn test_vec_borrow_mut() {
let mut v: Vec<u8> = vec![0x57, 0x72, 0x15];
let bstr1 = b"\x57\x72\x15";
let mut borrowed = v.borrow_foreign_mut();
unsafe {
assert_eq!(
libc::memcmp(
borrowed.as_ptr().cast::<c_void>(),
bstr1.as_ptr().cast::<c_void>(),
bstr1.len()
),
0
);
ptr::write(borrowed.as_mut_ptr().offset(1), 0xFF);
}
assert_eq!(v[1], 0xFF);
}
#[test]
fn test_vec_borrow_foreign_mut_clone_to_foreign() {
let mut v: Vec<u8> = vec![1, 2, 3];
let borrowed = v.borrow_foreign_mut();
let cloned = borrowed.clone_to_foreign();
assert_ne!(cloned.as_ptr(), borrowed.as_ptr());
unsafe {
assert_eq!(
libc::memcmp(
cloned.as_ptr().cast::<c_void>(),
borrowed.as_ptr().cast::<c_void>(),
3
),
0
);
}
}
}