use crate::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 AsIterOwn<T> {
fn iter_own<'a>(self: Own<'a, Self>) -> IterOwn<'a, T>;
}
const impl<T> AsIterOwn<T> for [T] {
fn iter_own<'a>(self: Own<'a, Self>) -> IterOwn<'a, T> {
IterOwn::new(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();
let ptr: NonNull<T> = NonNull::from_mut(unsafe { transmute::<_, &'a mut [T]>(slice) }).cast();
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]> {
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 => {
let len = unsafe { end_or_len.len };
if len == 0 { return None };
self.end_or_len = EndOrLen {
len: unsafe { len.unchecked_sub(1) },
};
},
false => {
let end = unsafe { end_or_len.end };
if unsafe { ptr.offset_from_unsigned(end) == 0 } { return None };
self.ptr = unsafe { ptr.add(1) };
}
}
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()
}
}
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
}
}
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;
}