You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
3.9 KiB

//! Iterators for `Populator`
use super::*;
use std::iter::{
self,
DoubleEndedIterator,
FusedIterator,
};
use std::fmt::{self, Debug};
#[derive(Debug, Clone)]
struct FullIter<T>(std::vec::IntoIter<T>);
#[derive(Debug)]
struct PartialIter<T>(std::vec::IntoIter<MaybeUninit<T>>,
std::vec::IntoIter<AtomicBool>, usize);
impl<T> Iterator for FullIter<T>
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<T> PartialIter<T> {
#[inline(always)]
fn next_raw(&mut self) -> Option<(MaybeUninit<T>, bool)>
{
let a = self.0.next()?;
let b = if cfg!(debug_assertions) { self.1.next()? } else { unsafe { self.1.next().unwrap_unchecked() } };
self.2-=1;
Some((a, b.into_inner()))
}
}
impl<T> Iterator for PartialIter<T>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
Some(loop {
match self.next_raw()? {
(value, true) => break unsafe { value.assume_init() },
_ => (),
}
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.2, Some(self.2))
}
}
impl<T> FusedIterator for FullIter<T>{}
impl<T> ExactSizeIterator for FullIter<T>{}
impl<T> FusedIterator for PartialIter<T>{}
impl<T> ExactSizeIterator for PartialIter<T>{}
trait PopulaterIter<T>: private::Sealed + Iterator<Item=T> + FusedIterator + ExactSizeIterator{
fn as_debug(&self) -> &dyn Debug
where T: Debug;
}
impl<T> private::Sealed for PartialIter<T>{}
impl<T> private::Sealed for FullIter<T>{}
impl<'a, T: 'a + Debug> Debug for dyn PopulaterIter<T> + 'a {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result
{
self.as_debug().fmt(fmt)
}
}
impl<T> PopulaterIter<T> for PartialIter<T>
{
#[inline(always)]
fn as_debug(&self) -> &dyn Debug
where T: Debug {
self
}
}
impl<T> PopulaterIter<T> for FullIter<T>
{
#[inline(always)]
fn as_debug(&self) -> &dyn Debug
where T: Debug {
self
}
}
#[derive(Debug)]
pub struct IntoIter<'a, T: 'a>(Box<dyn PopulaterIter<T> + 'a>);
/*
impl<'a, Iter, T: 'a> From<Iter> for IntoIter<'a, T>
where Iter: private::Sealed + PopulaterIter<T> + 'a
{
#[inline(always)]
fn from(v: Iter) -> Self {
Self(Box::new(v))
}
}
*/
#[inline(always)]
unsafe fn assume_init_boxed<T>(bx: Box<[MaybeUninit<T>]>) -> Box<[T]>
{
let raw = Box::into_raw(bx);
Box::from_raw(raw as *mut [T])
}
impl<'a, T> IntoIter<'a, T>
{
pub(super) fn create_from(mut pop: Populator<'a, T>) -> Self
{
Self(if pop.is_full_exclusive() {
let values = pop.take_values();
Box::new(FullIter(Vec::from(unsafe { assume_init_boxed(values) }).into_iter()))
} else {
let (values, populates) = pop.take_all();
Box::new(PartialIter(Vec::from(values).into_iter(),
Vec::from(populates).into_iter(),
*pop.populated.get_mut()))
})
}
}
impl<'a, T> Iterator for IntoIter<'a, T>
{
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a, T> FusedIterator for IntoIter<'a, T>{}
impl<'a, T> ExactSizeIterator for IntoIter<'a, T>{}
#[derive(Debug)]
struct FullIterRef<'a, T>(std::slice::Iter<'a, T>);
//struct PartialIterRef<'a, T>(&) //XXX: This probably isn't possible unless it takes an exclusive reference of Populator<'a, T>. Having to pass 'a around really sucks hey.
impl<'a, T> Iterator for FullIterRef<'a, T>
{
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a, T> DoubleEndedIterator for FullIterRef<'a, T>
{
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back()
}
}
impl<'a, T> FusedIterator for FullIterRef<'a, T>{}
impl<'a, T> ExactSizeIterator for FullIterRef<'a, T>{}