1pub trait Lines<'a> {
12 fn iter_forward(&'a self, limit: Option<usize>) -> impl Iterator<Item = &'a str>;
20
21 fn enumerate_forward(&'a self, limit: Option<usize>) -> impl Iterator<Item = (usize, &'a str)> {
29 self.iter_forward(limit).enumerate()
30 }
31
32 fn iter_backward(&'a self, limit: Option<usize>) -> impl DoubleEndedIterator<Item = &'a str>;
40
41 fn enumerate_tail_forward(&'a self, limit: usize) -> impl Iterator<Item = (usize, &'a str)> {
49 let start_offset = self.len().saturating_sub(limit);
50 self.iter_forward(None)
51 .skip(start_offset)
52 .enumerate()
53 .map(move |(i, s)| (i + start_offset, s))
54 }
55
56 fn enumerate_backward(
64 &'a self,
65 limit: Option<usize>,
66 ) -> impl Iterator<Item = (usize, &'a str)> {
67 let len = self.len();
68 self.iter_backward(limit)
69 .enumerate()
70 .map(move |(i, s)| (len - i - 1, s))
71 }
72
73 fn len(&self) -> usize;
78
79 fn is_empty(&self) -> bool;
84}
85
86impl<'a> Lines<'a> for Vec<&'a str> {
87 fn iter_forward(&'a self, limit: Option<usize>) -> impl Iterator<Item = &'a str> {
88 let limit = limit.unwrap_or(self.len());
89 self.iter().take(limit).cloned()
90 }
91
92 fn enumerate_tail_forward(&'a self, limit: usize) -> impl Iterator<Item = (usize, &'a str)> {
93 let start_offset = self.len().saturating_sub(limit);
94
95 self[start_offset..]
96 .iter()
97 .cloned()
98 .enumerate()
99 .map(move |(i, s)| (i + start_offset, s))
100 }
101
102 fn iter_backward(&'a self, limit: Option<usize>) -> impl DoubleEndedIterator<Item = &'a str> {
103 let limit = limit.unwrap_or(self.len());
104 self.iter().rev().take(limit).cloned()
105 }
106
107 fn len(&self) -> usize {
108 self.len()
109 }
110
111 fn is_empty(&self) -> bool {
112 self.is_empty()
113 }
114}
115
116impl<'a> Lines<'a> for Vec<String> {
117 fn iter_forward(&'a self, limit: Option<usize>) -> impl Iterator<Item = &'a str> {
118 let limit = limit.unwrap_or(self.len());
119 self.iter().take(limit).map(|s| s.as_str())
120 }
121
122 fn iter_backward(&'a self, limit: Option<usize>) -> impl DoubleEndedIterator<Item = &'a str> {
123 let limit = limit.unwrap_or(self.len());
124 self.iter().rev().take(limit).map(|s| s.as_str())
125 }
126
127 fn enumerate_tail_forward(&'a self, limit: usize) -> impl Iterator<Item = (usize, &'a str)> {
128 let start_offset = self.len().saturating_sub(limit);
129
130 self[start_offset..]
131 .iter()
132 .map(|s| s.as_str())
133 .enumerate()
134 .map(move |(i, s)| (i + start_offset, s))
135 }
136
137 fn len(&self) -> usize {
138 self.len()
139 }
140
141 fn is_empty(&self) -> bool {
142 self.is_empty()
143 }
144}
145
146impl<'a> Lines<'a> for &'a [&'a str] {
147 fn iter_forward(&'a self, limit: Option<usize>) -> impl Iterator<Item = &'a str> {
148 let limit = limit.unwrap_or(self.len());
149 self.iter().take(limit).cloned()
150 }
151
152 fn iter_backward(&'a self, limit: Option<usize>) -> impl DoubleEndedIterator<Item = &'a str> {
153 let limit = limit.unwrap_or(self.len());
154 self.iter().rev().take(limit).cloned()
155 }
156
157 fn enumerate_tail_forward(&'a self, limit: usize) -> impl Iterator<Item = (usize, &'a str)> {
158 let start_offset = self.len().saturating_sub(limit);
159
160 self[start_offset..]
161 .iter()
162 .cloned()
163 .enumerate()
164 .map(move |(i, s)| (i + start_offset, s))
165 }
166
167 fn len(&self) -> usize {
168 <[&str]>::len(self)
169 }
170
171 fn is_empty(&self) -> bool {
172 <[&str]>::is_empty(self)
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179
180 #[test]
181 fn test_iter_forward() {
182 let lines = vec!["a", "b", "c", "d", "e"];
183 let iter = lines.iter_forward(None);
184 assert_eq!(iter.collect::<Vec<_>>(), vec!["a", "b", "c", "d", "e"]);
185 let iter = lines.iter_forward(Some(3));
186 assert_eq!(iter.collect::<Vec<_>>(), vec!["a", "b", "c"]);
187 }
188
189 #[test]
190 fn test_iter_backward() {
191 let lines = vec!["a", "b", "c", "d", "e"];
192 let iter = lines.iter_backward(None);
193 assert_eq!(iter.collect::<Vec<_>>(), vec!["e", "d", "c", "b", "a"]);
194 let iter = lines.iter_backward(Some(3));
195 assert_eq!(iter.collect::<Vec<_>>(), vec!["e", "d", "c"]);
196 }
197
198 #[test]
199 fn test_enumerate_tail_forward() {
200 let lines = vec!["a", "b", "c", "d", "e"];
201 let iter = lines.enumerate_tail_forward(3);
202 assert_eq!(iter.collect::<Vec<_>>(), vec![(2, "c"), (3, "d"), (4, "e")]);
203 }
204
205 #[test]
206 fn test_enumerate_forward() {
207 let lines = vec!["a", "b", "c", "d", "e"];
208 let iter = lines.enumerate_forward(None);
209 assert_eq!(
210 iter.collect::<Vec<_>>(),
211 vec![(0, "a"), (1, "b"), (2, "c"), (3, "d"), (4, "e")]
212 );
213 let iter = lines.enumerate_forward(Some(3));
214 assert_eq!(iter.collect::<Vec<_>>(), vec![(0, "a"), (1, "b"), (2, "c")]);
215 }
216
217 #[test]
218 fn test_enumerate_backward() {
219 let lines = vec!["a", "b", "c", "d", "e"];
220 let iter = lines.enumerate_backward(None);
221 assert_eq!(
222 iter.collect::<Vec<_>>(),
223 vec![(4, "e"), (3, "d"), (2, "c"), (1, "b"), (0, "a")]
224 );
225 let iter = lines.enumerate_backward(Some(3));
226 assert_eq!(iter.collect::<Vec<_>>(), vec![(4, "e"), (3, "d"), (2, "c")]);
227 }
228
229 #[test]
230 fn test_string_vec_impl() {
231 let lines: Vec<String> = vec!["a".to_string(), "b".to_string(), "c".to_string()];
232 assert_eq!(lines.len(), 3);
233 assert!(!lines.is_empty());
234
235 let forward = lines.iter_forward(None).collect::<Vec<_>>();
237 assert_eq!(forward, vec!["a", "b", "c"]);
238
239 let limited = lines.iter_forward(Some(2)).collect::<Vec<_>>();
240 assert_eq!(limited, vec!["a", "b"]);
241
242 let backward = lines.iter_backward(None).collect::<Vec<_>>();
244 assert_eq!(backward, vec!["c", "b", "a"]);
245
246 let limited_backward = lines.iter_backward(Some(2)).collect::<Vec<_>>();
247 assert_eq!(limited_backward, vec!["c", "b"]);
248
249 let tail = lines.enumerate_tail_forward(2).collect::<Vec<_>>();
251 assert_eq!(tail, vec![(1, "b"), (2, "c")]);
252 }
253
254 #[test]
255 fn test_slice_impl() {
256 let slice = &["a", "b", "c"][..];
257 assert_eq!(slice.len(), 3);
258 assert!(!slice.is_empty());
259
260 let forward = slice.iter_forward(None).collect::<Vec<_>>();
262 assert_eq!(forward, vec!["a", "b", "c"]);
263
264 let limited = slice.iter_forward(Some(2)).collect::<Vec<_>>();
265 assert_eq!(limited, vec!["a", "b"]);
266
267 let backward = slice.iter_backward(None).collect::<Vec<_>>();
269 assert_eq!(backward, vec!["c", "b", "a"]);
270
271 let limited_backward = slice.iter_backward(Some(2)).collect::<Vec<_>>();
272 assert_eq!(limited_backward, vec!["c", "b"]);
273
274 let tail = slice.enumerate_tail_forward(2).collect::<Vec<_>>();
276 assert_eq!(tail, vec![(1, "b"), (2, "c")]);
277 }
278
279 #[test]
280 fn test_empty_collections() {
281 let empty_vec: Vec<&str> = Vec::new();
282 assert_eq!(empty_vec.len(), 0);
283 assert!(empty_vec.is_empty());
284 assert_eq!(empty_vec.iter_forward(None).count(), 0);
285 assert_eq!(empty_vec.iter_backward(None).count(), 0);
286 assert_eq!(empty_vec.enumerate_forward(None).count(), 0);
287 assert_eq!(empty_vec.enumerate_backward(None).count(), 0);
288 assert_eq!(empty_vec.enumerate_tail_forward(5).count(), 0);
289
290 let empty_string_vec: Vec<String> = Vec::new();
291 assert_eq!(empty_string_vec.len(), 0);
292 assert!(empty_string_vec.is_empty());
293 assert_eq!(empty_string_vec.iter_forward(None).count(), 0);
294 assert_eq!(empty_string_vec.iter_backward(None).count(), 0);
295
296 let empty_slice: &[&str] = &[];
297 assert_eq!(empty_slice.len(), 0);
298 assert!(empty_slice.is_empty());
299 assert_eq!(empty_slice.iter_forward(None).count(), 0);
300 assert_eq!(empty_slice.iter_backward(None).count(), 0);
301 }
302}