character_stream/
character_iter.rs1use std::{error::Error, io::Read};
2
3use crate::{
4 CharStream, CharacterStream, CharacterStreamResult, MultiPeek, MultiPeekable, Peek, Peekable,
5 PeekableCharacterStream, ToCharacterStream, TryToCharacterStream,
6};
7
8pub(crate) const INTERRUPTED_MAX: usize = 5;
9
10pub struct CharacterIterator<Stream: CharStream> {
12 pub(crate) stream: Stream,
14 pub(crate) interrupted_max: usize,
16 pub interrupted_count: usize,
17}
18
19impl<Stream: CharStream> CharacterIterator<Stream> {
20 pub fn new(stream: Stream, interrupted_max: usize) -> Self {
22 Self {
23 stream,
24 interrupted_max,
25 interrupted_count: 0,
26 }
27 }
28
29 pub fn stream(&self) -> &Stream {
31 &self.stream
32 }
33
34 pub fn stream_mut(&mut self) -> &mut Stream {
36 &mut self.stream
37 }
38
39 pub fn is_lossy(&self) -> bool {
41 self.stream.is_lossy()
42 }
43}
44
45impl<Reader: Read> CharacterIterator<CharacterStream<Reader>> {
46 pub fn peek(self) -> CharacterIterator<PeekableCharacterStream<Reader, Peek>> {
48 CharacterIterator::new(self.stream.peeky(), self.interrupted_max)
49 }
50
51 pub fn peek_multi(self) -> CharacterIterator<PeekableCharacterStream<Reader, MultiPeek>> {
53 CharacterIterator::new(self.stream.peeky_multi(), self.interrupted_max)
54 }
55}
56
57impl<Reader: Read> CharacterIterator<PeekableCharacterStream<Reader, Peek>> {
58 pub fn peek(&mut self) -> Option<&<Self as Iterator>::Item> {
60 self.stream.peek()
61 }
62}
63
64impl<Reader: Read> CharacterIterator<PeekableCharacterStream<Reader, MultiPeek>> {
65 pub fn peek(&mut self) -> Option<&<Self as Iterator>::Item> {
67 self.stream.peek()
68 }
69
70 pub fn reset_peek(&mut self) {
71 self.stream.reset_peek()
72 }
73}
74
75impl<Stream: CharStream + std::fmt::Debug> std::fmt::Debug for CharacterIterator<Stream> {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 write!(f, "{:?}", self)
78 }
79}
80
81impl<Stream: CharStream> Iterator for CharacterIterator<Stream> {
82 type Item = CharacterStreamResult;
83
84 fn next(&mut self) -> Option<Self::Item> {
85 match self.stream.read_char() {
86 Ok(character) => {
87 if self.interrupted_count > 0 {
88 self.interrupted_count = 0;
89 }
90
91 Some(Ok(character))
92 }
93 Err(error) => match error {
94 crate::CharacterError::NoBytesRead => None,
95 crate::CharacterError::IoError {
96 bytes: _,
97 error: ref err,
98 } => match err.kind() {
99 std::io::ErrorKind::Interrupted => {
100 if self.interrupted_count <= self.interrupted_max {
101 self.interrupted_count += 1;
102 self.next()
103 } else {
104 None
105 }
106 }
107 std::io::ErrorKind::UnexpectedEof => None,
108 _ => Some(Err(error)),
109 },
110 other => Some(Err(other)),
111 },
112 }
113 }
114}
115
116pub trait ToCharacterIterator<Reader: Read> {
120 fn to_character_iterator(&self) -> CharacterIterator<CharacterStream<Reader>>;
122
123 fn to_character_iterator_lossy(&self) -> CharacterIterator<CharacterStream<Reader>>;
125}
126
127impl<Reader: Read, T: ToCharacterStream<Reader>> ToCharacterIterator<Reader> for T {
128 fn to_character_iterator(&self) -> CharacterIterator<CharacterStream<Reader>> {
129 self.to_character_stream().into_iter()
130 }
131
132 fn to_character_iterator_lossy(&self) -> CharacterIterator<CharacterStream<Reader>> {
133 self.to_character_stream_lossy().into_iter()
134 }
135}
136
137pub trait TryToCharacterIterator<Reader: Read> {
139 fn try_to_character_iterator(
141 &self,
142 ) -> Result<CharacterIterator<CharacterStream<Reader>>, Box<dyn Error>>;
143
144 fn try_to_character_iterator_lossy(
146 &self,
147 ) -> Result<CharacterIterator<CharacterStream<Reader>>, Box<dyn Error>>;
148}
149
150impl<Reader: Read, T: TryToCharacterStream<Reader>> TryToCharacterIterator<Reader> for T {
151 fn try_to_character_iterator(
152 &self,
153 ) -> Result<CharacterIterator<CharacterStream<Reader>>, Box<dyn Error>> {
154 Ok(self.try_to_character_stream()?.into_iter())
155 }
156
157 fn try_to_character_iterator_lossy(
158 &self,
159 ) -> Result<CharacterIterator<CharacterStream<Reader>>, Box<dyn Error>> {
160 Ok(self.try_to_character_stream_lossy()?.into_iter())
161 }
162}