use core::ops::{Deref, DerefMut, Index, IndexMut};
use crate::{Deferred, Reference, SliceLike, SlicePointerIndex};
impl<T: Copy + Reference> Copy for Deferred<T> {}
impl<T: Clone + Copy + Reference> Clone for Deferred<T> {
fn clone(&self) -> Self {
*self
}
}
unsafe impl<T: Sync + Reference> Sync for Deferred<T> {}
unsafe impl<T: Send + Reference> Send for Deferred<T> {}
impl<T: Reference> Deref for Deferred<T> {
type Target = T::Target;
fn deref(&self) -> &Self::Target {
unsafe {
&*self.as_ptr()
}
}
}
impl<T: ?Sized> DerefMut for Deferred<&mut T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
&mut *self.as_mut_ptr()
}
}
}
impl<T: ?Sized> core::fmt::Pointer for Deferred<&T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
<*const T>::fmt(&self.as_ptr(), f)
}
}
impl<T: ?Sized> core::fmt::Pointer for Deferred<&mut T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
<*mut T>::fmt(&self.as_mut_ptr(), f)
}
}
impl<I, T> Index<I> for Deferred<T>
where
T: Reference,
T::Target: SliceLike,
I: SlicePointerIndex<T::Target>,
{
type Output = I::Output;
fn index(&self, index: I) -> &Self::Output {
unsafe {
&*index.index(self.as_ptr())
}
}
}
impl<I, T> IndexMut<I> for Deferred<&mut T>
where
T: SliceLike + ?Sized,
I: SlicePointerIndex<T>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
unsafe {
&mut *index.index_mut(self.as_mut_ptr())
}
}
}
impl<'a, T: ?Sized> From<Deferred<&'a mut T>> for Deferred<&'a T> {
fn from(deferred: Deferred<&mut T>) -> Self {
unsafe {
Deferred::from_raw(deferred.as_ptr())
}
}
}
impl<'a, T: ?Sized> From<&'a T> for Deferred<&'a T> {
fn from(reference: &T) -> Self {
unsafe {
Deferred::from_raw(reference)
}
}
}
impl<'a, T: ?Sized> From<&'a mut T> for Deferred<&'a mut T> {
fn from(reference: &mut T) -> Self {
unsafe {
Deferred::from_raw_mut(reference)
}
}
}
impl<'a, T, const N: usize> From<Deferred<&'a [T; N]>> for Deferred<&'a [T]> {
fn from(deferred: Deferred<&[T; N]>) -> Self {
unsafe {
Deferred::from_raw(core::ptr::slice_from_raw_parts(deferred.as_ptr() as *const T, N))
}
}
}
impl<'a, T, const N: usize> From<Deferred<&'a mut [T; N]>> for Deferred<&'a mut [T]> {
fn from(deferred: Deferred<&mut [T; N]>) -> Self {
unsafe {
Deferred::from_raw_mut(core::ptr::slice_from_raw_parts_mut(deferred.as_mut_ptr() as *mut T, N))
}
}
}
impl<'a, T, const N: usize> From<Deferred<&'a mut [T; N]>> for Deferred<&'a [T]> {
fn from(deferred: Deferred<&mut [T; N]>) -> Self {
unsafe {
Deferred::from_raw(core::ptr::slice_from_raw_parts(deferred.as_ptr() as *const T, N))
}
}
}
#[cfg(test)]
mod tests {
use crate::{Defer, DeferMut, Deferred};
use core::cell::UnsafeCell;
mod index {
use super::*;
#[test]
fn array() {
let mut buffer = [0u8; 1024];
let deferred = Deferred::from(&mut buffer);
assert_eq!(1024, (&deferred[..]).len());
let canary = unsafe { &mut deferred.clone_unchecked()[1000] };
assert_eq!(23, (&deferred[1001..]).len());
assert_eq!(&0, &deferred[0]);
assert_eq!(5, (&deferred[5..10]).len());
assert_eq!(10, (&deferred[..10]).len());
assert_eq!(11, (&deferred[..=10]).len());
assert_eq!(6, (&deferred[5..=10]).len());
assert_eq!(0, (&deferred[0..0]).len());
assert_eq!(1, (&deferred[0..1]).len());
assert_eq!(&mut 0, canary);
}
#[test]
fn array_mut() {
let mut buffer = [0u8; 1024];
let mut deferred = Deferred::from(&mut buffer);
assert_eq!(1024, (&mut deferred[..]).len());
let canary = unsafe { &mut deferred.clone_unchecked()[1000] };
assert_eq!(23, (&mut deferred[1001..]).len());
assert_eq!(&mut 0, &mut deferred[0]);
assert_eq!(5, (&mut deferred[5..10]).len());
assert_eq!(10, (&mut deferred[..10]).len());
assert_eq!(11, (&mut deferred[..=10]).len());
assert_eq!(6, (&mut deferred[5..=10]).len());
assert_eq!(0, (&mut deferred[0..0]).len());
assert_eq!(1, (&mut deferred[0..1]).len());
assert_eq!(&mut 0, canary);
}
#[test]
fn slice() {
let mut buffer = [0u8; 1024];
let deferred = Deferred::from(&mut buffer[..]);
let _x = &deferred[..];
#[cfg(feature = "slice_ptr_len")]
let canary = unsafe { &mut deferred.clone_unchecked()[1000] };
assert_eq!(23, (&deferred[1001..]).len());
assert_eq!(&0, &deferred[0]);
assert_eq!(5, (&deferred[5..10]).len());
assert_eq!(10, (&deferred[..10]).len());
assert_eq!(11, (&deferred[..=10]).len());
assert_eq!(6, (&deferred[5..=10]).len());
assert_eq!(0, (&deferred[0..0]).len());
assert_eq!(1, (&deferred[0..1]).len());
#[cfg(feature = "slice_ptr_len")]
assert_eq!(&mut 0, canary);
}
#[test]
fn slice_mut() {
let mut buffer = [0u8; 1024];
let mut deferred = Deferred::from(&mut buffer[..]);
let _x = &mut deferred[..];
#[cfg(feature = "slice_ptr_len")]
let canary = unsafe { &mut deferred.clone_unchecked()[1000] };
assert_eq!(23, (&mut deferred[1001..]).len());
assert_eq!(&mut 0, &mut deferred[0]);
assert_eq!(5, (&mut deferred[5..10]).len());
assert_eq!(10, (&mut deferred[..10]).len());
assert_eq!(11, (&mut deferred[..=10]).len());
assert_eq!(6, (&mut deferred[5..=10]).len());
assert_eq!(0, (&mut deferred[0..0]).len());
assert_eq!(1, (&mut deferred[0..1]).len());
#[cfg(feature = "slice_ptr_len")]
assert_eq!(&mut 0, canary);
}
}
mod from {
use super::*;
#[test]
fn from_ref() {
let buffer = [0u8; 1024];
let _deferred = Deferred::from(&buffer);
let _deferred: Deferred<&[u8]> = Deferred::from(&buffer[..]);
}
#[test]
fn from_mut() {
let mut buffer = [0u8; 1024];
let _deferred = Deferred::from(&mut buffer);
let _deferred: Deferred<&mut [u8]> = Deferred::from(&mut buffer[..]);
}
#[test]
fn ref_array_to_slice() {
let buffer = UnsafeCell::new([0u8; 1024]);
let deferred = buffer.defer();
let _deferred_slice: Deferred<&[u8]> = deferred.into();
let _deferred_slice: Deferred<&[u8]> = Deferred::from(deferred);
}
#[test]
fn mut_array_to_slice() {
let buffer = UnsafeCell::new([0u8; 1024]);
let deferred = unsafe { buffer.defer_mut() };
let _deferred_slice: Deferred<&mut [u8]> = deferred.into();
let deferred = unsafe { buffer.defer_mut() };
let _deferred_slice: Deferred<&mut [u8]> = Deferred::from(deferred);
}
#[test]
fn mut_array_to_ref_slice() {
let buffer = UnsafeCell::new([0u8; 1024]);
let deferred = unsafe { buffer.defer_mut() };
let _deferred_slice: Deferred<&[u8]> = deferred.into();
let deferred = unsafe { buffer.defer_mut() };
let _deferred_slice: Deferred<&[u8]> = Deferred::from(deferred);
}
#[test]
fn mut_to_ref() {
let buffer = UnsafeCell::new([0u8; 1024]);
let deferred = unsafe { buffer.defer_mut() };
let _deferred_slice: Deferred<&[u8; 1024]> = deferred.into();
let deferred = unsafe { buffer.defer_mut() };
let _deferred_slice: Deferred<&[u8; 1024]> = Deferred::from(deferred);
let buffer = UnsafeCell::new(1u32);
let deferred = unsafe { buffer.defer_mut() };
let _deferred_u32: Deferred<&u32> = deferred.into();
let deferred = unsafe { buffer.defer_mut() };
let _deferred_u32: Deferred<&u32> = Deferred::from(deferred);
}
}
}