expiring_ref 0.8.4

A crate designed to implement a mechanism for owning values, via a destructively-moved equivalent to C++'s xvalues/`T&&`
Documentation
use crate::{DerefMove, Own};
use core::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use core::marker::{Destruct, PhantomData};
use core::mem::{SizedTypeProperties, transmute_prefix as transmute};
use core::ptr::NonNull;
use core::slice::{Iter, IterMut};

const impl<'a, 'b: 'a, T> IntoIterator for &'a Own<'b, [T]> {
	type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
		self.iter()
	}
}
const impl<'a, 'b: 'a, T> IntoIterator for &'a mut Own<'b, [T]> {
	type Item = &'a mut T;
	type IntoIter = IterMut<'a, T>;

	fn into_iter(self) -> Self::IntoIter {
		self.iter_mut()
	}
}
const impl<'a, T> IntoIterator for Own<'a, [T]> {
	type Item = Own<'a, T>;
	type IntoIter = IterOwn<'a, T>;

	fn into_iter(self) -> Self::IntoIter {
		self.iter_own()
	}
}

pub impl(self) const trait ExpiringSliceIterExtension<T> {
	//noinspection RsNeedlessLifetimes
	fn iter_own<'a>(self: Own<'a, Self>) -> IterOwn<'a, T>;
	//noinspection RsNeedlessLifetimes
	fn iter_move<'a>(self: Own<'a, Self>) -> IterMove<'a, T>;
}

const impl<T> ExpiringSliceIterExtension<T> for [T] {
	//noinspection RsNeedlessLifetimes
	fn iter_own<'a>(self: Own<'a, Self>) -> IterOwn<'a, T> {
		IterOwn::new(self)
	}
	//noinspection RsNeedlessLifetimes
	fn iter_move<'a>(self: Own<'a, Self>) -> IterMove<'a, T> {
		IterMove::new(self)
	}
}


union EndOrLen<T> {
	end: NonNull<T>,
	len: usize,
}

impl<T> Copy for EndOrLen<T> {}
const impl<T> Clone for EndOrLen<T> {
	fn clone(&self) -> Self {
		*self
	}
}

pub struct IterOwn<'a, T> {
	ptr: NonNull<T>,

	end_or_len: EndOrLen<T>,
	void: PhantomData<Own<'a, T>>,
}

const impl<'a, T> IterOwn<'a, T> {
	#[inline(always)]
	fn new(slice: Own<'a, [T]>) -> Self {

		let len = slice.len();
		// SAFETY: the value is transparent around this
		let ptr: NonNull<T> = NonNull::from_mut(unsafe { transmute::<_, &'a mut [T]>(slice) }).cast();
		// SAFETY: the reference is valid, for non-zst types the end ptr is never dereferenced, for zst types it uses a length
		unsafe {
			let end_or_len = match const { T::IS_ZST } {
				true => EndOrLen { len },
				false => EndOrLen { end: ptr.add(len) }
			};

			Self { ptr, end_or_len, void: PhantomData }
		}
	}

	#[inline(always)]
	fn remaining_len(&self) -> usize {
		match const { <T as SizedTypeProperties>::IS_ZST } {
			true => unsafe { self.end_or_len.len },
			false => unsafe { self.end_or_len.end.offset_from_unsigned(self.ptr) }
		}
	}

	#[inline(always)]
	pub fn make_slice(&self) -> Own<'a, [T]> {
		// SAFETY: self originates from a valid slice
		unsafe { Own::new(NonNull::from_raw_parts(self.ptr, self.remaining_len()).as_mut()) }
	}
}

const impl<'a, T> Drop for IterOwn<'a, T> where T: [const] Destruct {
	fn drop(&mut self) {
		let range = self.make_slice();

		drop(range)
	}
}

const impl<'a, T> Iterator for IterOwn<'a, T> where T: [const] Destruct {
	type Item = Own<'a, T>;

	#[inline]
	fn next(&mut self) -> Option<Self::Item> {
		let ptr = self.ptr;
		let end_or_len = self.end_or_len;
		match const { <T as SizedTypeProperties>::IS_ZST } {
			true => {
				// SAFETY: will always be the right one
				let len = unsafe { end_or_len.len };
				if len == 0 { return None };
				self.end_or_len = EndOrLen {
					// SAFETY: `len` is always nonzero at this point
					len: unsafe { len.unchecked_sub(1) },
				};
			},
			false => {
				// SAFETY: will always be the right one
				let end = unsafe { end_or_len.end };
				// SAFETY: yes they derive from the same allocation
				if unsafe { ptr.offset_from_unsigned(end) == 0 } { return None };

				// SAFETY: same allocation => its valid and stuff
				self.ptr = unsafe { ptr.add(1) };
			}
		}

		// SAFETY: the ptr is a valid owned reference for the same lifetime so yeah
		Some(unsafe { transmute(ptr) })
	}

	#[inline]
	fn size_hint(&self) -> (usize, Option<usize>) {
		let exact = self.remaining_len();
		(exact, Some(exact))
	}

	#[inline]
	fn count(self) -> usize {
		self.remaining_len()
	}
}

unsafe impl<'a, T> TrustedRandomAccess for IterOwn<'a, T> {}

unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterOwn<'a, T> {
	const MAY_HAVE_SIDE_EFFECT: bool = false;
}

pub struct IterMove<'a, T>(IterOwn<'a, T>);

const impl<'a, T> IterMove<'a, T> {
	#[inline(always)]
	fn new(slice: Own<'a, [T]>) -> Self {
		Self(IterOwn::new(slice))
	}
}

const impl<'a, T> Iterator for IterMove<'a, T> where T: [const] Destruct {
	type Item = T;

	#[inline(always)]
	fn next(&mut self) -> Option<Self::Item> {
		Some(self.0.next()?.deref_move())
	}

	#[inline(always)]
	fn size_hint(&self) -> (usize, Option<usize>) {
		self.0.size_hint()
	}

	#[inline(always)]
	fn count(self) -> usize {
		self.0.count()
	}
}

unsafe impl<'a, T> TrustedRandomAccess for IterMove<'a, T> {}

unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMove<'a, T> {
	const MAY_HAVE_SIDE_EFFECT: bool = false;
}