diff options
author | Pierre-Antoine Champin <pchampin@liris.cnrs.fr> | 2018-10-08 13:35:16 +0200 |
---|---|---|
committer | Pierre-Antoine Champin <pchampin@liris.cnrs.fr> | 2018-10-08 13:35:16 +0200 |
commit | d4eb9928f18e9c4e96b0c47b8452ac3d373feb0b (patch) | |
tree | b79025e818349fcaffca1cbd269ba63d4530bf09 | |
parent | 8328b849cf8523bf931a4415c10823c48654b129 (diff) |
added map_x and while_ok
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/map_x.rs | 131 | ||||
-rw-r--r-- | src/while_ok.rs | 57 |
3 files changed, 190 insertions, 0 deletions
@@ -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()); +} |