parent
5bb0f854e9
commit
a88ed21e17
@ -1,139 +0,0 @@
|
|||||||
//! Useful iterators
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
|
|
||||||
/// An iterator that can yield `0,1,2+` items
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Either<T,U>
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
One(T),
|
|
||||||
Many(U),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T,U> Either<T,U>
|
|
||||||
{
|
|
||||||
pub fn take(&mut self) -> Self
|
|
||||||
{
|
|
||||||
std::mem::replace(self, Self::None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum EitherIter<T,U>
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
One(std::iter::Once<T>),
|
|
||||||
Many(std::iter::Fuse<U>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T,U> Iterator for EitherIter<T,U>
|
|
||||||
where U: Iterator<Item=T>
|
|
||||||
{
|
|
||||||
type Item = T;
|
|
||||||
fn next(&mut self) -> Option<Self::Item>
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
Self::None => None,
|
|
||||||
Self::One(one) => one.next(),
|
|
||||||
Self::Many(many) => many.next(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
||||||
match self {
|
|
||||||
Self::None => (0, Some(0)),
|
|
||||||
Self::One(_) => (1, Some(1)),
|
|
||||||
Self::Many(many) => many.size_hint(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T,U: Iterator<Item=T>> std::iter::FusedIterator for EitherIter<T,U>{}
|
|
||||||
impl<T,U: Iterator<Item=T>> std::iter::ExactSizeIterator for EitherIter<T,U>
|
|
||||||
where U: ExactSizeIterator{}
|
|
||||||
|
|
||||||
impl<T, U: IntoIterator<Item=T>> IntoIterator for Either<T, U>
|
|
||||||
{
|
|
||||||
type Item= T;
|
|
||||||
type IntoIter = EitherIter<T, <U as IntoIterator>::IntoIter>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
Self::None => EitherIter::None,
|
|
||||||
Self::One(one) => EitherIter::One(std::iter::once(one)),
|
|
||||||
Self::Many(many) => EitherIter::Many(many.into_iter().fuse())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A bespoke iterator type with an exact size
|
|
||||||
#[macro_export] macro_rules! over {
|
|
||||||
(@) => (0usize);
|
|
||||||
(@ $x:tt $($xs:tt)* ) => (1usize + $crate::over!(@ $($xs)*));
|
|
||||||
|
|
||||||
($($value:expr),*) => {
|
|
||||||
{
|
|
||||||
use ::std::mem::MaybeUninit;
|
|
||||||
use ::std::ops::Drop;
|
|
||||||
struct Arr<T>([MaybeUninit<T>; $crate::over!(@ $($value)*)], usize);
|
|
||||||
impl<T> Arr<T>
|
|
||||||
{
|
|
||||||
const LEN: usize = $crate::over!(@ $($value)*);
|
|
||||||
}
|
|
||||||
impl<T> Iterator for Arr<T>
|
|
||||||
{
|
|
||||||
type Item = T;
|
|
||||||
fn next(&mut self) -> Option<Self::Item>
|
|
||||||
{
|
|
||||||
if self.1 >= self.0.len() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
//take one
|
|
||||||
let one = unsafe {
|
|
||||||
::std::mem::replace(&mut self.0[self.1], MaybeUninit::uninit()).assume_init()
|
|
||||||
};
|
|
||||||
self.1+=1;
|
|
||||||
Some(one)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline] fn size_hint(&self) -> (usize, Option<usize>)
|
|
||||||
{
|
|
||||||
(Self::LEN, Some(Self::LEN))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T> ::std::iter::FusedIterator for Arr<T>{}
|
|
||||||
impl<T> ::std::iter::ExactSizeIterator for Arr<T>{}
|
|
||||||
|
|
||||||
impl<T> Drop for Arr<T>
|
|
||||||
{
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if ::std::mem::needs_drop::<T>() {
|
|
||||||
for idx in self.1..self.0.len() {
|
|
||||||
unsafe {
|
|
||||||
::std::mem::replace(&mut self.0[idx], MaybeUninit::uninit()).assume_init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Arr([$(MaybeUninit::new($value)),*], 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests
|
|
||||||
{
|
|
||||||
#[test]
|
|
||||||
fn iter_over()
|
|
||||||
{
|
|
||||||
const EXPECT: usize = 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1;
|
|
||||||
let iter = over![10,9,8,7,6,5,4,3,2,1];
|
|
||||||
|
|
||||||
assert_eq!(iter.len(), 10);
|
|
||||||
assert_eq!(iter.sum::<usize>(), EXPECT);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue