summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre-Antoine Champin <pchampin@liris.cnrs.fr>2018-10-08 13:35:16 +0200
committerPierre-Antoine Champin <pchampin@liris.cnrs.fr>2018-10-08 13:35:16 +0200
commitd4eb9928f18e9c4e96b0c47b8452ac3d373feb0b (patch)
treeb79025e818349fcaffca1cbd269ba63d4530bf09
parent8328b849cf8523bf931a4415c10823c48654b129 (diff)
added map_x and while_ok
-rw-r--r--src/lib.rs2
-rw-r--r--src/map_x.rs131
-rw-r--r--src/while_ok.rs57
3 files changed, 190 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index f8fb768..d949faa 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -109,10 +109,12 @@
//!
pub mod errors;
+pub mod map_x;
pub mod oks;
pub mod onerr;
pub mod onok;
pub mod prelude;
pub mod unwrap;
+pub mod while_ok;
mod util;
diff --git a/src/map_x.rs b/src/map_x.rs
new file mode 100644
index 0000000..a328dd1
--- /dev/null
+++ b/src/map_x.rs
@@ -0,0 +1,131 @@
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+/// Extension trait for `Iterator<Item = Result<O, E>>` to iter until an error is encountered.
+pub trait MapX<O, E> : Sized
+{
+ fn map_ok<F, O2>(self, F) -> MapOk<Self, F>
+ where F: FnMut(O) -> O2;
+ fn map_err<F, E2>(self, F) -> MapErr<Self, F>
+ where F: FnMut(E) -> E2;
+}
+
+impl<I, O, E> MapX<O, E> for I
+ where I: Iterator<Item = Result<O, E>> + Sized,
+{
+ fn map_ok<F, O2>(self, f: F) -> MapOk<Self, F>
+ where F: FnMut(O) -> O2
+ {
+ MapOk{ iter: self, f }
+ }
+ fn map_err<F, E2>(self, f: F) -> MapErr<Self, F>
+ where F: FnMut(E) -> E2
+ {
+ MapErr{ iter: self, f }
+ }
+}
+
+
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+pub struct MapOk<I, F> {
+ iter: I,
+ f: F,
+}
+
+impl<I, O, E, F, O2> Iterator for MapOk<I, F>
+ where I: Iterator<Item = Result<O, E>>,
+ F: FnMut(O) -> O2,
+{
+ type Item = Result<O2, E>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|r| r.map(&mut self.f))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+pub struct MapErr<I, F> {
+ iter: I,
+ f: F,
+}
+
+impl<I, O, E, F, E2> Iterator for MapErr<I, F>
+ where I: Iterator<Item = Result<O, E>>,
+ F: FnMut(E) -> E2,
+{
+ type Item = Result<O, E2>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|r| r.map_err(&mut self.f))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+
+#[test]
+fn test_map_ok() {
+ use std::str::FromStr;
+
+ let mapped: Vec<_> = ["1", "2", "a", "4", "5"]
+ .into_iter()
+ .map(|txt| usize::from_str(txt))
+ .map_ok(|i| 2*i)
+ .collect();
+
+ assert_eq!(mapped[0], Ok(2));
+ assert_eq!(mapped[1], Ok(4));
+ assert_eq!(mapped[3], Ok(8));
+ assert_eq!(mapped[4], Ok(10));
+}
+
+#[test]
+fn test_map_ok_hint() {
+ use std::str::FromStr;
+
+ let hint = ["1", "2", "a", "4", "5"]
+ .into_iter()
+ .map(|txt| usize::from_str(txt))
+ .map_ok(|i| 2*i)
+ .size_hint();
+
+ assert_eq!(hint, (5, Some(5)));
+}
+
+#[test]
+fn test_map_err() {
+ use std::str::FromStr;
+
+ let mapped: Vec<_> = ["1", "2", "a", "4", "5"]
+ .into_iter()
+ .map(|txt| usize::from_str(txt))
+ .map_err(|e| format!("{:?}", e))
+ .collect();
+
+ assert_eq!(mapped[2], Err("ParseIntError { kind: InvalidDigit }".to_string()));
+}
+
+#[test]
+fn test_map_err_hint() {
+ use std::str::FromStr;
+
+ let hint = ["1", "2", "a", "4", "5"]
+ .into_iter()
+ .map(|txt| usize::from_str(txt))
+ .map_err(|e| format!("{:?}", e))
+ .size_hint();
+
+ assert_eq!(hint, (5, Some(5)));
+}
diff --git a/src/while_ok.rs b/src/while_ok.rs
new file mode 100644
index 0000000..ef5c03f
--- /dev/null
+++ b/src/while_ok.rs
@@ -0,0 +1,57 @@
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+/// Extension trait for `Iterator<Item = Result<O, E>>` to iter until an error is encountered.
+pub trait WhileOk<O, E>
+{
+ fn while_ok<F>(self, F) -> Result<(), E>
+ where F: FnMut(O) -> ();
+}
+
+impl<I, O, E> WhileOk<O, E> for I
+ where I: Iterator<Item = Result<O, E>>,
+{
+ fn while_ok<F>(self, mut f: F) -> Result<(), E>
+ where F: FnMut(O) -> ()
+ {
+ for res in self {
+ f(res?);
+ }
+ Ok(())
+ }
+}
+
+
+
+#[test]
+fn test_while_ok_ok() {
+ use std::str::FromStr;
+
+ let mut s = 0;
+
+ let res = ["1", "2", "3", "4", "5"]
+ .into_iter()
+ .map(|txt| usize::from_str(txt))
+ .while_ok(|i| s += i);
+
+ assert_eq!(s, 15);
+ assert!(res.is_ok());
+}
+
+#[test]
+fn test_while_ok_err() {
+ use std::str::FromStr;
+
+ let mut s = 0;
+
+ let res = ["1", "2", "a", "4", "5"]
+ .into_iter()
+ .map(|txt| usize::from_str(txt))
+ .while_ok(|i| s += i);
+
+ assert_eq!(s, 3);
+ assert!(res.is_err());
+}