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
10pub(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
48pub(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}