From 0c3f630880ddf9e70c231c17657cf3e09fec3a72 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 26 Feb 2021 12:51:15 +0000 Subject: [PATCH] utils: Provide Loop (infallible version) Signed-off-by: Ian Jackson --- src/lib.rs | 1 + src/prelude.rs | 2 +- src/utils.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 0fdd5a48..1be3cd3f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: AGPL-3.0-or-later // There is NO WARRANTY. +#![feature(type_alias_impl_trait)] #![allow(clippy::redundant_closure_call)] pub mod imports; diff --git a/src/prelude.rs b/src/prelude.rs index 13a14d53..ec5007b9 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -13,7 +13,7 @@ pub use std::cmp::{self, max, min, Ordering}; pub use std::collections::VecDeque; pub use std::collections::{btree_set, BTreeSet}; pub use std::collections::{hash_map, HashMap, HashSet}; -pub use std::convert::{TryFrom, TryInto}; +pub use std::convert::{Infallible, TryFrom, TryInto}; pub use std::env; pub use std::error::Error; pub use std::fmt::Formatter; diff --git a/src/utils.rs b/src/utils.rs index e8d86826..7b38ccb8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -292,3 +292,55 @@ macro_rules! deref_to_field_mut { } } } + +#[derive(Debug)] +pub enum Loop { + Continue, + Break, + Error(E), +} +impl From for Loop { + fn from(e: E) -> Loop { Loop::Error(e) } +} + +pub trait IteratorExt<'f,U,E,F>: Iterator + where F: 'f + FnMut(Self::Item) -> Result>, +{ + type R1: Iterator; + fn map_loop(self, f: F) -> Self::R1 where E: EmptyType; +/* + fn try_map_loop< + U, E, + F: FnMut(Self::Item) -> Result> + >(self, f: &mut F) -> impl Iterator> { + self + .map(f) + .filter(|i| matches!(i, Err(Loop::Continue))) + .take_while(|i| matches!(i, Err(Loop::Break))) + .map(|i| match i { + Ok(y) => Ok(y), + Err(Loop::Error(e)) => Err(e), + _ => panic!(), + }) + }*/ +} + +pub trait EmptyType { fn diverge(self) -> T; } + +impl EmptyType for Infallible { + fn diverge(self) -> T { match self { } } +} + +impl<'f,T,U,E,F> IteratorExt<'f,U,E,F> for T where + T: 'f + Iterator, + F: 'f + FnMut(Self::Item) -> Result>, +{ + type R1 = impl Iterator + 'f; + fn map_loop(self, f: F) -> Self::R1 where E: EmptyType { + self + .map(f) + .filter(|i| !matches!(i, Err(Loop::Continue))) + .take_while(|i| !matches!(i, Err(Loop::Break))) + .map(|i| i.ok().unwrap()) + } +} -- 2.30.2