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