character_stream/
character_iter.rs

1use 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
10/// Iterator over a [CharacterStream](crate::CharacterStream)
11pub struct CharacterIterator<Stream: CharStream> {
12    /// The stream to iterate over.
13    pub(crate) stream: Stream,
14    /// Maximum amount of [Interrupted](std::io::ErrorKind::Interrupted) errors.
15    pub(crate) interrupted_max: usize,
16    pub interrupted_count: usize,
17}
18
19impl<Stream: CharStream> CharacterIterator<Stream> {
20    /// Create a iterator from a [CharacterStream](crate::CharacterStream)
21    pub fn new(stream: Stream, interrupted_max: usize) -> Self {
22        Self {
23            stream,
24            interrupted_max,
25            interrupted_count: 0,
26        }
27    }
28
29    /// Return a reference to the underlying stream.
30    pub fn stream(&self) -> &Stream {
31        &self.stream
32    }
33
34    /// Return a mutable reference to the underlying stream.
35    pub fn stream_mut(&mut self) -> &mut Stream {
36        &mut self.stream
37    }
38
39    /// Is the character parser lossy?
40    pub fn is_lossy(&self) -> bool {
41        self.stream.is_lossy()
42    }
43}
44
45impl<Reader: Read> CharacterIterator<CharacterStream<Reader>> {
46    /// Make the underlying stream peekable.
47    pub fn peek(self) -> CharacterIterator<PeekableCharacterStream<Reader, Peek>> {
48        CharacterIterator::new(self.stream.peeky(), self.interrupted_max)
49    }
50
51    /// Make the underlying stream multi-peekable
52    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    /// Peek the next character in the stream.
59    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    /// Peek the next character in the stream. (multi-peek)
66    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
116// impl<Stream: CharStream> FusedIterator for CharacterIterator<Stream> {}
117
118/// Trait for easy conversion of a type into a [CharacterIterator].
119pub trait ToCharacterIterator<Reader: Read> {
120    /// Convert into a [CharacterIterator].
121    fn to_character_iterator(&self) -> CharacterIterator<CharacterStream<Reader>>;
122
123    /// Convert into a lossy [CharacterIterator].
124    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
137/// Trait for easy conversion of a type into a [CharacterIterator] with a potential for failure.
138pub trait TryToCharacterIterator<Reader: Read> {
139    /// Attempt to convert into a [CharacterIterator].
140    fn try_to_character_iterator(
141        &self,
142    ) -> Result<CharacterIterator<CharacterStream<Reader>>, Box<dyn Error>>;
143
144    /// Attempt to convert into a lossy [CharacterIterator].
145    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}