iof/read/
iter.rs

1use super::read_one_from::ReadOneFromError;
2use crate::{
3    ext::PatternError,
4    fmt::Format,
5    stream::{error::StreamError, line_buf::LineBuf, traits::BufReadExtWithFormat},
6    BufReadExt, ReadError, ReadOneFrom,
7};
8use std::{any::type_name, marker::PhantomData};
9
10/// Iterator for all elements.
11pub(super) struct ReadAll<'s, F: Format, S: ?Sized, T: ReadOneFrom> {
12    format: F,
13    stream: &'s mut S,
14    phantom: PhantomData<T>,
15}
16
17impl<'s, F: Format, S: ?Sized, T: ReadOneFrom> ReadAll<'s, F, S, T> {
18    #[inline]
19    pub(crate) fn new(stream: &'s mut S, format: F) -> Self {
20        let phantom = PhantomData;
21        Self {
22            format,
23            stream,
24            phantom,
25        }
26    }
27}
28
29impl<F: Format, S: BufReadExt + ?Sized, T: ReadOneFrom> Iterator for ReadAll<'_, F, S, T> {
30    type Item = Result<T, ReadOneFromError<T>>;
31
32    #[inline]
33    fn next(&mut self) -> Option<Self::Item> {
34        match self
35            .stream
36            .try_get_string_some(self.format.skip(), T::accept())
37        {
38            Ok(s) => Some(T::parse(s)),
39            Err(PatternError::Extra(StreamError::Eof | StreamError::Eol)) => None,
40            Err(PatternError::Extra(e)) => Some(Err(e.into())),
41            Err(PatternError::UnexpectedChar(e)) => {
42                Some(Err(ReadError::UnexpectedChar(e, type_name::<T>())))
43            }
44        }
45    }
46}
47
48/// Iterator for all elements in a string.
49pub(super) struct ReadAllIn<'s, F: Format, T: ReadOneFrom> {
50    format: F,
51    stream: LineBuf<'s>,
52    phantom: PhantomData<T>,
53}
54
55impl<'s, F: Format, T: ReadOneFrom> ReadAllIn<'s, F, T> {
56    #[inline]
57    pub(crate) fn new(buffer: &'s str, format: F) -> Self {
58        let stream = LineBuf::new(buffer);
59        let phantom = PhantomData;
60        Self {
61            format,
62            stream,
63            phantom,
64        }
65    }
66}
67
68impl<F: Format, T: ReadOneFrom> Iterator for ReadAllIn<'_, F, T> {
69    type Item = Result<T, ReadOneFromError<T>>;
70
71    #[inline]
72    fn next(&mut self) -> Option<Self::Item> {
73        match T::try_read_one_from(&mut self.stream, self.format) {
74            Ok(t) => Some(Ok(t)),
75            Err(ReadError::EOF | ReadError::EOL) => None,
76            Err(e) => Some(Err(e)),
77        }
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84    use crate::{
85        fmt::Default,
86        stream::{ext::Any, line_buf::LineBuf},
87        unwrap, InputStream, ReadInto,
88    };
89    use std::io::Cursor;
90
91    #[test]
92    fn line_buf_strings() {
93        let s = "Hello, world!";
94        let mut buf = LineBuf::new(s);
95        let iter = ReadAll::new(&mut buf, Default::new());
96        let res: Result<Vec<String>, _> = iter.collect();
97        let res = unwrap!(res);
98        assert_eq!(res, vec!["Hello,", "world!"]);
99    }
100
101    #[test]
102    fn input_stream_strings() {
103        let s = "Hello, world!";
104        let mut buf = InputStream::new(Cursor::new(s));
105        let skip = Default::new();
106        let iter = ReadAll::new(&mut buf, &skip);
107        let res: Result<Vec<String>, _> = iter.collect();
108        let res = unwrap!(res);
109        assert_eq!(res, vec!["Hello,", "world!"]);
110    }
111
112    #[test]
113    #[should_panic = "expect more characters before EOL"]
114    fn line_buf_string() {
115        let s = "\n";
116        let mut buf = LineBuf::new(s);
117        let _: &str = unwrap!(buf.try_get_string_some(Default::<char>::new().skip(), Any::new()));
118    }
119
120    #[test]
121    #[should_panic = "expect more characters before EOF"]
122    fn input_stream_string() {
123        let s = "\n";
124        let mut buf = InputStream::new(Cursor::new(s));
125        let _: &str = unwrap!(buf.try_get_string_some(Default::<char>::new().skip(), Any::new()));
126    }
127
128    #[test]
129    #[should_panic = "expect more characters before EOL"]
130    fn line_buf_tuple() {
131        let s = "1 2";
132        let mut buf = LineBuf::new(s);
133        let _: (f64, f64, f64) = unwrap!(buf.try_read());
134    }
135
136    #[test]
137    #[should_panic = "expect more characters before EOF"]
138    fn input_stream_tuple() {
139        let s = "1 2";
140        let mut buf = InputStream::new(Cursor::new(s));
141        let _: (f64, f64, f64) = unwrap!(buf.try_read());
142    }
143}