chiark / gitweb /
utils: Provide Loop (infallible version)
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 26 Feb 2021 12:51:15 +0000 (12:51 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 26 Feb 2021 12:51:15 +0000 (12:51 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/lib.rs
src/prelude.rs
src/utils.rs

index 0fdd5a480aaf1f5e29617163a45b694ae62a28a0..1be3cd3ff47c76c2112b24e34b496f1221433d13 100644 (file)
@@ -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;
index 13a14d53a863d34f3db6da410e82d80e40c2b7c0..ec5007b904a20fc447e2b8fd8d5494b4cb5aafef 100644 (file)
@@ -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;
index e8d86826a996500c32b1ec9f3f313991d3eb4bb7..7b38ccb8aae2fcb957db71c6b5d6d852583f7fe4 100644 (file)
@@ -292,3 +292,55 @@ macro_rules! deref_to_field_mut {
     }
   }
 }
+
+#[derive(Debug)]
+pub enum Loop<E> {
+  Continue,
+  Break,
+  Error(E),
+}
+impl<E> From<E> for Loop<E> {
+  fn from(e: E) -> Loop<E> { Loop::Error(e) }
+}
+
+pub trait IteratorExt<'f,U,E,F>: Iterator
+  where F: 'f + FnMut(Self::Item) -> Result<U,Loop<E>>,
+{
+  type R1: Iterator<Item=U>;
+  fn map_loop(self, f: F) -> Self::R1 where E: EmptyType;
+/*
+  fn try_map_loop<
+    U, E,
+    F: FnMut(Self::Item) -> Result<U,Loop<E>>
+  >(self, f: &mut F) -> impl Iterator<Result<U>> {
+    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<T>(self) -> T; }
+
+impl EmptyType for Infallible {
+  fn diverge<T>(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<U,Loop<E>>,
+{
+  type R1 = impl Iterator<Item=U> + '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())
+  }
+}