1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::IMExIter;
use std::io::Result;

/// Trait for merging iterators into an [`IMExIter`](./struct.IMExIter.html)
pub trait IMExMerges<T, I>
where
    T: Iterator<Item = I>,
{
    /// Define how self, a vector of iterators, and an IMEx string merge into an
    /// [`IMExIter`](./struct.IMExIter.html)
    ///
    /// In practice, this is used to merge more than two iterators with a custom IMEx.
    ///
    /// # Error
    /// Results in an error if the provided IMEx is invalid.
    ///
    /// # Example
    /// ```
    /// use imex::IMExMerges;
    ///
    /// let merged = "12345"
    ///     .chars()
    ///     .imex_merge_all(&mut vec!["abcde".chars(), "!@#$%".chars()], "0(1120)*")
    ///     .expect("Invalid IMEx")
    ///     .collect::<String>();
    ///
    /// assert_eq!(merged, "1ab!2cd@3e#4$5%");
    /// ```
    fn imex_merge_all(self, iters: &mut Vec<T>, imex: &str) -> Result<IMExIter<T, I>>;

    /// Merges many iterators using a rotating IMEx. The resulting iterator will consume 1 item
    /// from the provided iterators, in order, until they are all exhausted.
    ///
    /// # Example
    /// ```
    /// use imex::IMExMerges;
    ///
    /// let merged = "1234"
    ///     .chars()
    ///     .rot_merge_all(&mut vec!["abcdefg".chars(), "!@#".chars()])
    ///     .collect::<String>();
    ///
    /// assert_eq!(merged, "1a!2b@3c#4defg");
    /// ```
    fn rot_merge_all(self, iters: &mut Vec<T>) -> IMExIter<T, I>
    where
        Self: Sized,
    {
        let iter_count = (iters.len() + 1) as u8;
        let imex = format!(
            "({})*",
            (0..iter_count)
                .map(|x| format!("{}", x))
                .collect::<String>()
        );
        self.imex_merge_all(iters, &imex)
            .expect("Default imex should have been valid, but wasn't")
    }

    /// Merges two iterators (self and other) using a custom IMEx.
    ///
    /// # Error
    /// Results in an error if the provided IMEx is invalid.
    ///
    /// # Example
    /// ```
    /// use imex::IMExMerges;
    ///
    /// let merged = "12345"
    ///     .chars()
    ///     .imex_merge("ab".chars(), "0*1*")
    ///     .expect("Invalid IMEx")
    ///     .collect::<String>();
    ///
    /// assert_eq!(merged, "12345ab");
    /// ```
    fn imex_merge(self, other: T, imex: &str) -> Result<IMExIter<T, I>>
    where
        Self: Sized,
    {
        self.imex_merge_all(&mut vec![other], imex)
    }

    /// Merges two iterators (self and other) using an alternating IMEx. The resulting iterator
    /// will consume 1 item from self and other, alternating, until they are both exhausted.
    ///
    /// # Example
    /// ```
    /// use imex::IMExMerges;
    ///
    /// let merged = "12"
    ///     .chars()
    ///     .alt_merge("ab".chars())
    ///     .collect::<String>();
    ///
    /// assert_eq!(merged, "1a2b");
    /// ```
    fn alt_merge(self, other: T) -> IMExIter<T, I>
    where
        Self: Sized,
    {
        self.imex_merge(other, "(01)*")
            .expect("Default imex should have been valid, but wasn't")
    }
}

impl<T, I> IMExMerges<T, I> for T
where
    T: Iterator<Item = I>,
{
    fn imex_merge_all(self, iters: &mut Vec<T>, imex: &str) -> Result<IMExIter<T, I>> {
        let mut total_iters = vec![self];
        total_iters.append(iters);
        IMExIter::<T, I>::new(total_iters, imex)
    }
}