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 if let Some(item) = inner.next() {
84 return Some((self.outer_index - 1, item)); }
86 }
87
88 let next_outer = self.iter.next()?;
90 self.current_inner = Some(next_outer.into_iter());
91 self.outer_index += 1;
92 }
94 }
95
96 fn size_hint(&self) -> (usize, Option<usize>) {
97 let (inner_lower, inner_upper) = self
98 .current_inner
99 .as_ref()
100 .map_or((0, None), |inner| inner.size_hint());
101
102 let (outer_lower, outer_upper) = self.iter.size_hint();
103
104 let lower = inner_lower.saturating_add(outer_lower);
105 let upper = match (inner_upper, outer_upper) {
106 (Some(i), Some(o)) => i.checked_add(o),
107 _ => None,
108 };
109
110 (lower, upper)
111 }
112}
113
114impl<I> FusedIterator for FlattenWithIndex<I>
116where
117 I: Iterator + FusedIterator,
118 I::Item: IntoIterator,
119 <I::Item as IntoIterator>::IntoIter: FusedIterator,
120{
121}
122
123pub trait FlattenWithIndexExt: Iterator {
124 fn flatten_with_index(self) -> FlattenWithIndex<Self>
125 where
126 Self::Item: IntoIterator,
127 Self: Sized,
128 {
129 FlattenWithIndex::new(self)
130 }
131}
132
133impl<T: Iterator> FlattenWithIndexExt for T {}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn test_flatten_with_index() {
141 let data = vec![vec!['a', 'b'], vec!['c', 'd'], vec!['e', 'f', 'g']];
143
144 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
145
146 let expected = vec![
147 (0, 'a'),
148 (0, 'b'),
149 (1, 'c'),
150 (1, 'd'),
151 (2, 'e'),
152 (2, 'f'),
153 (2, 'g'),
154 ];
155 assert_eq!(result, expected);
156
157 let data: Vec<Vec<char>> = Vec::new();
159 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
160 assert!(result.is_empty());
161
162 let data = vec![
164 vec!['a', 'b'],
165 vec![], vec!['c', 'd'],
167 ];
168
169 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
170
171 let expected = vec![(0, 'a'), (0, 'b'), (2, 'c'), (2, 'd')];
172 assert_eq!(result, expected);
173
174 let data = vec![
176 vec!['a', 'b'],
177 vec![], vec!['c'],
179 vec![], vec!['d', 'e', 'f'],
181 ];
182
183 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
184
185 let expected = vec![(0, 'a'), (0, 'b'), (2, 'c'), (4, 'd'), (4, 'e'), (4, 'f')];
186
187 assert_eq!(result, expected);
188
189 let data = vec![vec![], vec![], vec![]];
191
192 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
193
194 assert!(result.is_empty());
195
196 let data = vec![vec!['a', 'b', 'c']];
198
199 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
200
201 let expected = vec![(0, 'a'), (0, 'b'), (0, 'c')];
202
203 assert_eq!(result, expected);
204
205 let data = vec![
207 vec!['a'], vec!['b', 'c'], vec!['d'], ];
211
212 let result: Vec<(usize, char)> = data.into_iter().flatten_with_index().collect();
213
214 let expected = vec![(0, 'a'), (1, 'b'), (1, 'c'), (2, 'd')];
215
216 assert_eq!(result, expected);
217 }
218}