1pub mod clone_ext;
20pub mod config;
21pub mod config_value;
22pub mod content;
23pub mod context;
24pub mod error;
25pub mod filename;
26mod filter;
27mod front_matter;
28#[cfg(feature = "renderer")]
29pub mod highlight;
30pub mod html;
31#[cfg(feature = "renderer")]
32pub mod html2md;
33pub mod html_renderer;
34#[cfg(feature = "lang-detection")]
35pub mod lingua;
36pub mod markup_language;
37mod note;
38pub mod settings;
39pub mod template;
40pub mod text_reader;
41pub mod workflow;
42
43use std::iter::FusedIterator;
44
45pub struct FlattenWithIndex<I>
48where
49 I: Iterator,
50 I::Item: IntoIterator,
51{
52 iter: I,
53 current_inner: Option<<I::Item as IntoIterator>::IntoIter>,
54 outer_index: usize, }
56
57impl<I> FlattenWithIndex<I>
58where
59 I: Iterator,
60 I::Item: IntoIterator,
61{
62 pub fn new(iter: I) -> Self {
64 Self {
65 iter,
66 current_inner: None,
67 outer_index: 0,
68 }
69 }
70}
71
72impl<I> Iterator for FlattenWithIndex<I>
73where
74 I: Iterator,
75 I::Item: IntoIterator,
76{
77 type Item = (usize, <I::Item as IntoIterator>::Item);
78
79 fn next(&mut self) -> Option<Self::Item> {
80 loop {
81 if let Some(inner) = &mut self.current_inner
83 && let Some(item) = inner.next() {
84 return Some((self.outer_index - 1, item)); }
86
87 let next_outer = self.iter.next()?;
89 self.current_inner = Some(next_outer.into_iter());
90 self.outer_index += 1;
91 }
93 }
94
95 fn size_hint(&self) -> (usize, Option<usize>) {
96 let (inner_lower, inner_upper) = self
97 .current_inner
98 .as_ref()
99 .map_or((0, None), |inner| inner.size_hint());
100
101 let (outer_lower, outer_upper) = self.iter.size_hint();
102
103 let lower = inner_lower.saturating_add(outer_lower);
104 let upper = match (inner_upper, outer_upper) {
105 (Some(i), Some(o)) => i.checked_add(o),
106 _ => None,
107 };
108
109 (lower, upper)
110 }
111}
112
113impl<I> FusedIterator for FlattenWithIndex<I>
115where
116 I: Iterator + FusedIterator,
117 I::Item: IntoIterator,
118 <I::Item as IntoIterator>::IntoIter: FusedIterator,
119{
120}
121
122pub trait FlattenWithIndexExt: Iterator {
123 fn flatten_with_index(self) -> FlattenWithIndex<Self>
124 where
125 Self::Item: IntoIterator,
126 Self: Sized,
127 {
128 FlattenWithIndex::new(self)
129 }
130}
131
132impl<T: Iterator> FlattenWithIndexExt for T {}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn test_flatten_with_index() {
140 let data = vec![vec!['a', 'b'], vec!['c', 'd'], vec!['e', 'f', 'g']];
142
143 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
144
145 let expected = vec![
146 (0, 'a'),
147 (0, 'b'),
148 (1, 'c'),
149 (1, 'd'),
150 (2, 'e'),
151 (2, 'f'),
152 (2, 'g'),
153 ];
154 assert_eq!(result, expected);
155
156 let data: Vec<Vec<char>> = Vec::new();
158 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
159 assert!(result.is_empty());
160
161 let data = vec![
163 vec!['a', 'b'],
164 vec![], vec!['c', 'd'],
166 ];
167
168 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
169
170 let expected = vec![(0, 'a'), (0, 'b'), (2, 'c'), (2, 'd')];
171 assert_eq!(result, expected);
172
173 let data = vec![
175 vec!['a', 'b'],
176 vec![], vec!['c'],
178 vec![], vec!['d', 'e', 'f'],
180 ];
181
182 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
183
184 let expected = vec![(0, 'a'), (0, 'b'), (2, 'c'), (4, 'd'), (4, 'e'), (4, 'f')];
185
186 assert_eq!(result, expected);
187
188 let data = vec![vec![], vec![], vec![]];
190
191 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
192
193 assert!(result.is_empty());
194
195 let data = vec![vec!['a', 'b', 'c']];
197
198 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
199
200 let expected = vec![(0, 'a'), (0, 'b'), (0, 'c')];
201
202 assert_eq!(result, expected);
203
204 let data = vec![
206 vec!['a'], vec!['b', 'c'], vec!['d'], ];
210
211 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
212
213 let expected = vec![(0, 'a'), (1, 'b'), (1, 'c'), (2, 'd')];
214
215 assert_eq!(result, expected);
216 }
217}