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