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
6use crate::grid::records::IntoRecords;
7
8use 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)]
13pub struct BufRows<I, T> {
14 iter: I,
15 buf: Vec<T>,
16}
17
18impl 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
38impl<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
45impl<I, T> From<BufRows<I, T>> for BufColumns<I>
46where
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
64impl<I, T> IntoRecords for BufRows<I, T>
65where
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)]
84pub struct BufRowIter<I, T> {
85 buf: std::vec::IntoIter<T>,
86 iter: I,
87}
88
89impl<I, T> Iterator for BufRowIter<I, T>
90where
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)]
110pub struct BufColumns<I> {
111 iter: I,
112 buf: Vec<Vec<String>>,
113}
114
115impl 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
141impl<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
148impl<I> IntoRecords for BufColumns<I>
149where
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)]
168pub struct BufColumnIter<I> {
169 buf: std::vec::IntoIter<Vec<String>>,
170 iter: I,
171}
172
173impl<I> Iterator for BufColumnIter<I>
174where
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)]
194pub enum EitherRowIterator<I> {
195 /// Allocated iterator.
196 Owned(std::vec::IntoIter<String>),
197 /// Given iterator.
198 Some(I),
199}
200
201impl<I> Iterator for EitherRowIterator<I>
202where
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