Skip to main content

iterate_text/file/
characters.rs

1#!/usr/bin/env rust
2
3
4//! Reads from path, buffer, or descriptor and iterates over characters until EOF is reached
5//!
6//! > Depends on [IterateFileLines]
7//!
8//! # Example
9//!
10//! ```rust
11//! use iterate_text::file::characters::IterateFileCharacters;
12//!
13//! let p = "tests/file/characters/file.txt";
14//! let mut c = IterateFileCharacters::new(p);
15//!
16//! assert_eq!(c.next(), Some('T'));
17//! assert_eq!(c.next(), Some('h'));
18//! assert_eq!(c.next(), Some('i'));
19//! assert_eq!(c.next(), Some('s'));
20//! ```
21//!
22//! [IterateFileLines]: ../lines/index.html
23
24
25use std::io::BufReader;
26use std::fs::File;
27
28use crate::file::lines::IterateFileLines;
29use crate::string::characters::IterateStringCharacters;
30
31
32/// Wraps [`IterateFileLines`][IterateFileLines] and implements Iterator for `.chars()`
33///
34/// [IterateFileLines]: ../lines/index.html
35#[derive(Debug)]
36pub struct IterateFileCharacters {
37    line_buffer: IterateFileLines,
38    char_buffer: Option<IterateStringCharacters>,
39}
40
41
42impl IterateFileCharacters {
43    /// Initializes structure for file `path`
44    pub fn new<S>(path: S) -> Self
45    where
46        S: Into<String>
47    {
48        let line_buffer = IterateFileLines::new(path);
49        let char_buffer = None;
50        Self { line_buffer, char_buffer }
51    }
52}
53
54impl Iterator for IterateFileCharacters {
55    type Item = char;
56
57    /// Returns `Some<char>` when a character is available from `.read_line()`
58    /// or `None` when EOF (End Of File) is reached.
59    fn next(&mut self) -> Option<Self::Item> {
60        loop {
61            if let Some(chars) = self.char_buffer.as_mut() {
62                if let Some(c) = chars.next() {
63                    return Some(c);
64                }
65            }
66
67            if let Some(line) = self.line_buffer.next() {
68                self.char_buffer = Some(IterateStringCharacters::new(line));
69            } else {
70                return None;
71            }
72        }
73    }
74}
75
76
77impl From<File> for IterateFileCharacters {
78    /// Initializes structure from `File` descriptor
79    fn from(file_descriptor: File) -> Self {
80        Self {
81            line_buffer: IterateFileLines::from(file_descriptor),
82            char_buffer: None,
83        }
84    }
85}
86
87impl From<BufReader<File>> for IterateFileCharacters {
88    /// Initializes structure from `BufReader<File>`
89    fn from(buffer_reader: BufReader<File>) -> Self {
90        Self {
91            line_buffer: IterateFileLines::from(buffer_reader),
92            char_buffer: None,
93        }
94    }
95}
96