use crate::{Deferred, PointerLength, Reference, SliceLike, SlicePointerIndex};
impl<T> Deferred<T>
where
T: Reference,
T::Target: SliceLike,
{
pub fn len(&self) -> usize {
PointerLength::len(self.as_ptr())
}
#[inline]
pub fn get<I>(&self, index: I) -> Option<&I::Output>
where
I: SlicePointerIndex<T::Target>,
{
index.get(self.as_ptr()).map(|ptr| {
unsafe { &*ptr }
})
}
#[inline]
pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
where
I: SlicePointerIndex<T::Target>,
{
&*index.get_unchecked(self.as_ptr())
}
#[inline]
pub unsafe fn split_at_unchecked(&self, mid: usize) -> (Deferred<&[<T::Target as SliceLike>::Element]>, Deferred<&[<T::Target as SliceLike>::Element]>){
(
Deferred::from_raw((..mid).get_unchecked(self.as_ptr())),
Deferred::from_raw((mid..).get_unchecked(self.as_ptr()))
)
}
#[inline]
pub fn split_at(&self, mid: usize) -> (Deferred<&[<T::Target as SliceLike>::Element]>, Deferred<&[<T::Target as SliceLike>::Element]>) {
assert!(mid <= self.len());
unsafe { self.split_at_unchecked(mid) }
}
}
impl<T> Deferred<&mut T>
where
T: SliceLike + ?Sized,
{
#[inline]
pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
where
I: SlicePointerIndex<T>,
{
index.get_mut(self.as_mut_ptr()).map(|ptr| {
unsafe { &mut *ptr }
})
}
#[inline]
pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
where
I: SlicePointerIndex<T>,
{
&mut *index.get_unchecked_mut(self.as_mut_ptr())
}
#[inline]
pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (Deferred<&mut [T::Element]>, Deferred<&mut [T::Element]>) {
(
Deferred::from_raw_mut((..mid).get_unchecked_mut(self.as_mut_ptr())),
Deferred::from_raw_mut((mid..).get_unchecked_mut(self.as_mut_ptr()))
)
}
#[inline]
pub fn split_at_mut(&mut self, mid: usize) -> (Deferred<&mut [T::Element]>, Deferred<&mut [T::Element]>) {
assert!(mid <= self.len());
unsafe { self.split_at_mut_unchecked(mid) }
}
}
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use alloc::boxed::Box;
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use crate::{DeferMut, Deferred};
#[test]
fn doctest1() {
let mut buffer = [0u8; 300];
let mut a = Deferred::from(&mut buffer); let b = unsafe { a.clone_unchecked().into_ref() }; let mut c = unsafe { a.clone_unchecked() }; let mut_ref1 = &mut a[0..100];
assert_eq!(&[0u8; 100], &b[100..200]);
c[200..].copy_from_slice(&[1u8; 100]);
assert_eq!(&mut [1u8; 100], &mut c[200..]);
assert_eq!(&mut [0u8; 100], mut_ref1);
}
#[test]
fn doctest2() {
let mut buffer = [0u8; 300];
let mut a: Deferred<&mut [u8]> = Deferred::from(&mut buffer).into(); let b = unsafe { a.clone_unchecked().into_ref() }; let mut c = unsafe { a.clone_unchecked() }; let mut_ref1 = &mut a.deref_mut()[0..100]; assert_eq!(&mut [0u8; 100], &mut mut_ref1[0..100]); assert_eq!(&[0u8; 100], &b.deref()[100..200]); c.deref_mut()[200..].copy_from_slice(&[1u8; 100]); assert_eq!(&mut [1u8; 100], &mut c.deref_mut()[200..]); }
#[test]
fn len_array() {
let mut buffer = [0u8; 1024];
let ptr = core::ptr::addr_of!(buffer);
let deferred = unsafe { Deferred::from_raw(ptr) };
assert_eq!(1024, deferred.len());
let ptr = core::ptr::addr_of_mut!(buffer);
let deferred = unsafe { Deferred::from_raw_mut(ptr) };
assert_eq!(1024, deferred.len());
}
#[test]
fn len_slice() {
let mut buffer = Vec::with_capacity(1024);
buffer.resize(1024, 0u8);
let ptr = &buffer[..] as *const [u8];
let deferred = unsafe { Deferred::from_raw(ptr) };
Deferred::len(&deferred);
assert_eq!(1024, deferred.len());
let ptr = core::ptr::slice_from_raw_parts_mut(buffer.as_mut_ptr(), buffer.len());
let deferred = unsafe { Deferred::from_raw_mut(ptr) };
assert_eq!(1024, deferred.len());
}
#[test]
fn test_array_len_ub() {
let buffer = UnsafeCell::new([0u8; 1024]);
let mut deferred = unsafe { buffer.defer_mut() };
let mut_borrow = unsafe { &mut *(deferred.deref_mut() as *mut [u8; 1024]) };
assert_eq!(1024, deferred.len()); assert_eq!(0, mut_borrow[0]);
}
#[test]
fn test_slice_len_ub() {
let mut vector = Vec::with_capacity(1024);
vector.resize(1024, 0u8);
let boxed_slice = vector.into_boxed_slice();
let buffer: Box<UnsafeCell<[u8]>> = unsafe { core::mem::transmute(boxed_slice) };
let mut deferred = unsafe { buffer.defer_mut() };
let mut_borrow = unsafe { &mut *(deferred.deref_mut() as *mut [u8]) };
assert_eq!(1024, deferred.len()); assert_eq!(0, mut_borrow[0]);
}
#[test]
fn core_split_at_mut() {
let mut buffer = [1, 2, 3];
let mut_ref = &mut buffer;
let (left, right) = mut_ref.split_at_mut(1);
assert_eq!(&mut [1], left);
assert_eq!(&mut [2, 3], right);
assert_eq!([1, 2, 3], *mut_ref);
}
}