parity_map/
lib.rs

1//! For mapping integers based on their parity
2
3use either::Either::{self, Left, Right};
4use num::Integer;
5
6/// Methods for mapping an integer by its parity
7pub trait ParityMap<MapOddErr, MapEvenErr>: Sized + Integer {
8    /// Applies a function to `self` if it's odd.
9    /// # Errors
10    /// If `self` is odd, but the function called on it fails, an `MapOddError` is returned.
11    fn map_odd<F>(self, odd_fn: F) -> Result<Self, MapOddErr>
12    where
13        F: FnOnce(Self) -> Result<Self, MapOddErr>,
14    {
15        if self.is_odd() {
16            odd_fn(self)
17        } else {
18            Ok(self)
19        }
20    }
21
22    /// Applies a function to `self` if it's even.
23    /// # Errors
24    /// If `self` is even, but the function called on it fails, a `MapEvenError` is returned.
25    fn map_even<F>(self, even_fn: F) -> Result<Self, MapEvenErr>
26    where
27        F: FnOnce(Self) -> Result<Self, MapEvenErr>,
28    {
29        if self.is_even() {
30            even_fn(self)
31        } else {
32            Ok(self)
33        }
34    }
35
36    /// Applies `even_fn` to `self` if it's even, else `odd_fn` is applied.
37    /// # Errors
38    /// If `self` is even, but the function called on it fails, a `MapEvenError` is returned.
39    fn parity_map<Odd, Even>(
40        self,
41        even_fn: Even,
42        odd_fn: Odd,
43    ) -> Result<Self, Either<MapEvenErr, MapOddErr>>
44    where
45        Odd: FnOnce(Self) -> Result<Self, MapOddErr>,
46        Even: FnOnce(Self) -> Result<Self, MapEvenErr>,
47    {
48        if self.is_even() {
49            even_fn(self).map_err(Left)
50        } else {
51            odd_fn(self).map_err(Right)
52        }
53    }
54}
55
56impl<T, O, E> ParityMap<O, E> for T where T: Sized + Integer {}