use crate::LendingIterator;
use core::fmt;
#[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Fuse<I> {
iter: Option<I>,
}
impl<I> Fuse<I> {
pub(crate) fn new(iter: I) -> Self {
Self { iter: Some(iter) }
}
}
impl<I: fmt::Debug> fmt::Debug for Fuse<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Fuse").field("iter", &self.iter).finish()
}
}
impl<I> LendingIterator for Fuse<I>
where
I: LendingIterator,
{
type Item<'a>
= I::Item<'a>
where
Self: 'a;
#[inline]
fn next(&mut self) -> Option<Self::Item<'_>> {
let self_ = unsafe { &mut *(self as *mut Self) };
let iter = self_.iter.as_mut()?;
if let Some(item) = iter.next() {
Some(item)
} else {
self.iter = None;
None
}
}
#[inline]
#[allow(clippy::redundant_closure_for_method_calls)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter
.as_ref()
.map_or((0, Some(0)), |iter| iter.size_hint())
}
}
#[cfg(test)]
mod tests {
use crate::{LendingIterator, ToLendingIterator};
struct OneThenError {
yielded: bool,
}
impl OneThenError {
fn new() -> Self {
Self { yielded: false }
}
}
impl LendingIterator for OneThenError {
type Item<'a>
= i32
where
Self: 'a;
fn next(&mut self) -> Option<Self::Item<'_>> {
if self.yielded {
None
} else {
self.yielded = true;
Some(1)
}
}
}
fn identity(x: i32) -> i32 {
x
}
#[test]
fn fuse_basic() {
let mut iter = OneThenError::new().fuse();
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
}
#[test]
fn fuse_regular_iter() {
let result: Vec<_> = (0..5)
.into_lending()
.fuse()
.map(identity)
.into_iter()
.collect();
assert_eq!(result, vec![0, 1, 2, 3, 4]);
}
}