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
117
118
119
120
121
122
123
124
125
126
/// Cover text iterator which traverses the text word by word.
/// It also enables the user to peek the word without forwarding the iterator.
#[derive(Debug)]
pub struct CoverTextWordIterator {
    words: Vec<String>,
    word_index: usize,
}

/// Cover text iterator which traverses the text line by line.
#[derive(Debug)]
pub struct CoverTextLineIterator {
    lines: Vec<String>,
    line_index: usize,
}

impl CoverTextWordIterator {
    pub fn new(cover_text: &str) -> Self {
        CoverTextWordIterator {
            words: cover_text
                .split_whitespace()
                .collect::<Vec<&str>>()
                .iter()
                .map(|v| v.to_string())
                .collect(),
            word_index: 0,
        }
    }

    /// # Examples
    ///
    /// ## Returns the next word without forwarding the iterator
    /// ```
    /// use ptero::text::CoverTextWordIterator;
    ///
    /// let text = "a b c d e;";
    /// let iter: CoverTextWordIterator = CoverTextWordIterator::new(&text);
    ///
    /// assert_eq!(iter.peek(), Some("a".to_owned()));
    /// assert_eq!(iter.peek(), Some("a".to_owned()));
    /// ```
    pub fn peek(&self) -> Option<String> {
        self.words
            .get(self.word_index)
            .map(|string| string.to_owned())
    }
}

impl Iterator for CoverTextWordIterator {
    type Item = String;

    /// # Examples
    ///
    /// ## Returns the next word
    /// ```
    /// use ptero::text::CoverTextWordIterator;
    ///
    /// let text = "a b c";
    /// let mut iter: CoverTextWordIterator = CoverTextWordIterator::new(&text);
    ///
    /// assert_eq!(iter.next(), Some("a".to_owned()));
    /// assert_eq!(iter.next(), Some("b".to_owned()));
    /// ```
    /// ## Returns `None` when iterator has traversed all the words and does not repeat
    /// ```
    /// use ptero::text::CoverTextWordIterator;
    ///
    /// let text = "a b c";
    /// let mut iter: CoverTextWordIterator = CoverTextWordIterator::new(&text);
    ///
    /// assert_eq!(iter.next(), Some("a".to_owned()));
    /// assert_eq!(iter.next(), Some("b".to_owned()));
    /// assert_eq!(iter.next(), Some("c".to_owned()));
    /// assert_eq!(iter.next(), None);
    /// assert_eq!(iter.next(), None);
    /// ```
    fn next(&mut self) -> Option<Self::Item> {
        let word = self.peek()?;
        self.word_index += 1;
        Some(word)
    }
}

impl CoverTextLineIterator {
    pub fn new(cover_text: &str) -> Self {
        CoverTextLineIterator {
            lines: cover_text
                .lines()
                .map(|v| v.to_string())
                .collect::<Vec<String>>(),
            line_index: 0,
        }
    }
}

impl Iterator for CoverTextLineIterator {
    type Item = String;

    /// # Examples
    ///
    /// ## Returns the next line
    /// ```
    /// use ptero::text::CoverTextLineIterator;
    ///
    /// let text = "a b c";
    /// let mut iter: CoverTextLineIterator = CoverTextLineIterator::new(&text);
    ///
    /// assert_eq!(iter.next(), Some("a b c".to_owned()));
    /// ```
    /// ## Returns `None` when traversed all the lines and does not repeat
    /// ```
    /// use ptero::text::CoverTextLineIterator;
    ///
    /// let text = "a b c\na";
    /// let mut iter: CoverTextLineIterator = CoverTextLineIterator::new(&text);
    ///
    /// assert_eq!(iter.next(), Some("a b c".to_owned()));
    /// assert_eq!(iter.next(), Some("a".to_owned()));
    /// assert_eq!(iter.next(), None);
    /// assert_eq!(iter.next(), None);
    /// ```
    fn next(&mut self) -> Option<Self::Item> {
        let line = self.lines.get(self.line_index).map(|x| x.to_owned())?;
        self.line_index += 1;
        Some(line)
    }
}