1 | //! A module contains [`BufRows`] and [`BufColumns`] iterators. |
2 | //! |
3 | //! Almoust always they both can be used interchangeably but [`BufRows`] is supposed to be lighter cause it |
4 | //! does not reads columns. |
5 | |
6 | use crate::grid::records::IntoRecords; |
7 | |
8 | use super::either_string::EitherString; |
9 | |
10 | /// BufRecords inspects [`IntoRecords`] iterator and keeps read data buffered. |
11 | /// So it can be checking before hand. |
12 | #[derive (Debug)] |
13 | pub struct BufRows<I, T> { |
14 | iter: I, |
15 | buf: Vec<T>, |
16 | } |
17 | |
18 | impl BufRows<(), ()> { |
19 | /// Creates a new [`BufRows`] structure, filling the buffer. |
20 | pub fn new<I: IntoRecords>( |
21 | records: I, |
22 | sniff: usize, |
23 | ) -> BufRows<<I::IterRows as IntoIterator>::IntoIter, I::IterColumns> { |
24 | let mut buf: Vec<::IterColumns> = vec![]; |
25 | |
26 | let mut iter: ::IterRows = records.iter_rows().into_iter(); |
27 | for _ in 0..sniff { |
28 | match iter.next() { |
29 | Some(row: ::IterColumns) => buf.push(row), |
30 | None => break, |
31 | } |
32 | } |
33 | |
34 | BufRows { iter, buf } |
35 | } |
36 | } |
37 | |
38 | impl<I, T> BufRows<I, T> { |
39 | /// Returns a slice of a record buffer. |
40 | pub fn as_slice(&self) -> &[T] { |
41 | &self.buf |
42 | } |
43 | } |
44 | |
45 | impl<I, T> From<BufRows<I, T>> for BufColumns<I> |
46 | where |
47 | T: IntoIterator, |
48 | T::Item: AsRef<str>, |
49 | { |
50 | fn from(value: BufRows<I, T>) -> Self { |
51 | let buf: Vec> = valueimpl Iterator- >
|
52 | .buf |
53 | .into_iter() |
54 | .map(|row: T| row.into_iter().map(|s: ::Item| s.as_ref().to_string()).collect()) |
55 | .collect(); |
56 | |
57 | BufColumns { |
58 | iter: value.iter, |
59 | buf, |
60 | } |
61 | } |
62 | } |
63 | |
64 | impl<I, T> IntoRecords for BufRows<I, T> |
65 | where |
66 | I: Iterator<Item = T>, |
67 | T: IntoIterator, |
68 | T::Item: AsRef<str>, |
69 | { |
70 | type Cell = T::Item; |
71 | type IterColumns = T; |
72 | type IterRows = BufRowIter<I, T>; |
73 | |
74 | fn iter_rows(self) -> Self::IterRows { |
75 | BufRowIter { |
76 | buf: self.buf.into_iter(), |
77 | iter: self.iter, |
78 | } |
79 | } |
80 | } |
81 | |
82 | /// Buffered [`Iterator`]. |
83 | #[derive (Debug)] |
84 | pub struct BufRowIter<I, T> { |
85 | buf: std::vec::IntoIter<T>, |
86 | iter: I, |
87 | } |
88 | |
89 | impl<I, T> Iterator for BufRowIter<I, T> |
90 | where |
91 | I: Iterator<Item = T>, |
92 | T: IntoIterator, |
93 | T::Item: AsRef<str>, |
94 | { |
95 | type Item = T; |
96 | |
97 | fn next(&mut self) -> Option<Self::Item> { |
98 | match self.buf.next() { |
99 | Some(i: T) => Some(i), |
100 | None => self.iter.next(), |
101 | } |
102 | } |
103 | } |
104 | |
105 | /// BufRecords inspects [`IntoRecords`] iterator and keeps read data buffered. |
106 | /// So it can be checking before hand. |
107 | /// |
108 | /// In contrast to [`BufRows`] it keeps records by columns. |
109 | #[derive (Debug)] |
110 | pub struct BufColumns<I> { |
111 | iter: I, |
112 | buf: Vec<Vec<String>>, |
113 | } |
114 | |
115 | impl BufColumns<()> { |
116 | /// Creates new [`BufColumns`] structure, filling the buffer. |
117 | pub fn new<I: IntoRecords>( |
118 | records: I, |
119 | sniff: usize, |
120 | ) -> BufColumns<<I::IterRows as IntoIterator>::IntoIter> { |
121 | let mut buf = vec![]; |
122 | |
123 | let mut iter = records.iter_rows().into_iter(); |
124 | for _ in 0..sniff { |
125 | match iter.next() { |
126 | Some(row) => { |
127 | let row = row |
128 | .into_iter() |
129 | .map(|cell| cell.as_ref().to_string()) |
130 | .collect::<Vec<_>>(); |
131 | buf.push(row) |
132 | } |
133 | None => break, |
134 | } |
135 | } |
136 | |
137 | BufColumns { iter, buf } |
138 | } |
139 | } |
140 | |
141 | impl<I> BufColumns<I> { |
142 | /// Returns a slice of a keeping buffer. |
143 | pub fn as_slice(&self) -> &[Vec<String>] { |
144 | &self.buf |
145 | } |
146 | } |
147 | |
148 | impl<I> IntoRecords for BufColumns<I> |
149 | where |
150 | I: Iterator, |
151 | I::Item: IntoIterator, |
152 | <I::Item as IntoIterator>::Item: AsRef<str>, |
153 | { |
154 | type Cell = EitherString<<I::Item as IntoIterator>::Item>; |
155 | type IterColumns = EitherRowIterator<<I::Item as IntoIterator>::IntoIter>; |
156 | type IterRows = BufColumnIter<I>; |
157 | |
158 | fn iter_rows(self) -> Self::IterRows { |
159 | BufColumnIter { |
160 | buf: self.buf.into_iter(), |
161 | iter: self.iter, |
162 | } |
163 | } |
164 | } |
165 | |
166 | /// A row iterator for [`BufColumns`] |
167 | #[derive (Debug)] |
168 | pub struct BufColumnIter<I> { |
169 | buf: std::vec::IntoIter<Vec<String>>, |
170 | iter: I, |
171 | } |
172 | |
173 | impl<I> Iterator for BufColumnIter<I> |
174 | where |
175 | I: Iterator, |
176 | I::Item: IntoIterator, |
177 | <I::Item as IntoIterator>::Item: AsRef<str>, |
178 | { |
179 | type Item = EitherRowIterator<<I::Item as IntoIterator>::IntoIter>; |
180 | |
181 | fn next(&mut self) -> Option<Self::Item> { |
182 | match self.buf.next() { |
183 | Some(i: Vec) => Some(EitherRowIterator::Owned(i.into_iter())), |
184 | None => self |
185 | .iter |
186 | .next() |
187 | .map(|i: ::Item| EitherRowIterator::Some(i.into_iter())), |
188 | } |
189 | } |
190 | } |
191 | |
192 | /// An iterator over some iterator or allocated buffer. |
193 | #[derive (Debug)] |
194 | pub enum EitherRowIterator<I> { |
195 | /// Allocated iterator. |
196 | Owned(std::vec::IntoIter<String>), |
197 | /// Given iterator. |
198 | Some(I), |
199 | } |
200 | |
201 | impl<I> Iterator for EitherRowIterator<I> |
202 | where |
203 | I: Iterator, |
204 | { |
205 | type Item = EitherString<I::Item>; |
206 | |
207 | fn next(&mut self) -> Option<Self::Item> { |
208 | match self { |
209 | EitherRowIterator::Owned(iter: &mut IntoIter) => iter.next().map(EitherString::Owned), |
210 | EitherRowIterator::Some(iter: &mut I) => iter.next().map(EitherString::Some), |
211 | } |
212 | } |
213 | } |
214 | |