Skip to main content

iterate_text/string/
characters.rs

1#!/usr/bin/env rust
2
3
4//! This file
5//!
6//! # Example
7//!
8//! ```rust
9//! use iterate_text::string::characters::IterateStringCharacters;
10//!
11//! let s = String::from("test!");
12//! let mut c = IterateStringCharacters::new(s);
13//!
14//! assert_eq!(c.next(), Some('t'));
15//! assert_eq!(c.next(), Some('e'));
16//! assert_eq!(c.next(), Some('s'));
17//! assert_eq!(c.next(), Some('t'));
18//! assert_eq!(c.next(), Some('!'));
19//! assert_eq!(c.next(), None);
20//! ```
21
22
23/// Iterates over characters within string owned string
24#[derive(Debug)]
25pub struct IterateStringCharacters {
26    data: Option<(String, usize)>,
27}
28
29
30impl IterateStringCharacters {
31    /// Assumes ownership of `string` and returns new instance of `IterateStringCharacters`
32    pub fn new<S>(string: S) -> Self
33    where
34        S: Into<String>
35    {
36        let string: String = string.into();
37        let index: usize = 0;
38        let data = Some((string, index));
39        Self { data }
40    }
41}
42
43
44impl Iterator for IterateStringCharacters {
45    type Item = char;
46
47    /// Increments index to the next character and returns current character, which avoids
48    /// reallocation inefficacies. However, there are likely improvements that could be made by
49    /// implementing some form of buffer that holds more than one line at a time in memory.
50    fn next(&mut self) -> Option<Self::Item> {
51        if let Some((string, index)) = self.data.take() {
52            let mut iter = string.get(index..).unwrap().char_indices();
53            if let Some((_, c)) = iter.next() {
54                self.data = iter.next().map(|(i, _)| (string, index + i));
55                return Some(c);
56            }
57        }
58        None
59    }
60}
61