iter_identify_first_last/
lib.rs1#![cfg_attr(feature="nightly", feature(trusted_len))]
2
3#![deny(warnings)]
4#![doc(test(attr(deny(warnings))))]
5#![doc(test(attr(allow(dead_code))))]
6#![doc(test(attr(allow(unused_variables))))]
7#![allow(clippy::needless_doctest_main)]
8#![allow(clippy::type_complexity)]
9
10#![doc=document_features::document_features!()]
12
13#![no_std]
14
15#[doc=include_str!("../README.md")]
16type _DocTestReadme = ();
17
18use core::fmt::{self, Debug, Formatter};
19use core::iter::{FusedIterator, Map, Peekable};
20#[cfg(feature="nightly")]
21use core::iter::TrustedLen;
22use core::mem::replace;
23
24pub struct IdentifyFirstLast<I: Iterator>(
29 Map<IdentifyFirst<IdentifyLast<I>>, fn((bool, (bool, I::Item))) -> (bool, bool, I::Item)>
30);
31
32impl<I: Iterator + Debug> Debug for IdentifyFirstLast<I> where I::Item: Debug {
33 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { self.0.fmt(f) }
34}
35
36impl<I: Iterator + Clone> Clone for IdentifyFirstLast<I> where I::Item: Clone {
37 fn clone(&self) -> Self { IdentifyFirstLast(self.0.clone()) }
38}
39
40impl<I: Iterator> Iterator for IdentifyFirstLast<I> {
41 type Item = (bool, bool, I::Item);
42
43 fn next(&mut self) -> Option<Self::Item> { self.0.next() }
44
45 fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
46}
47
48#[cfg(feature="nightly")]
49unsafe impl<I: TrustedLen> TrustedLen for IdentifyFirstLast<I> { }
50
51impl<I: ExactSizeIterator> ExactSizeIterator for IdentifyFirstLast<I> {
52 fn len(&self) -> usize { self.0.len() }
53}
54
55impl<I: FusedIterator> FusedIterator for IdentifyFirstLast<I> { }
56
57pub struct IdentifyLast<I: Iterator> {
62 iter: Peekable<I>,
63}
64
65impl<I: Iterator + Debug> Debug for IdentifyLast<I> where I::Item: Debug {
66 fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { self.iter.fmt(f) }
67}
68
69impl<I: Iterator + Clone> Clone for IdentifyLast<I> where I::Item: Clone {
70 fn clone(&self) -> Self { IdentifyLast { iter: self.iter.clone() } }
71}
72
73impl<I: Iterator> Iterator for IdentifyLast<I> {
74 type Item = (bool, I::Item);
75
76 fn next(&mut self) -> Option<Self::Item> {
77 if let Some(item) = self.iter.next() {
78 let is_last = self.iter.peek().is_none();
79 Some((is_last, item))
80 } else {
81 None
82 }
83 }
84
85 fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
86}
87
88#[cfg(feature="nightly")]
89unsafe impl<I: TrustedLen> TrustedLen for IdentifyLast<I> { }
90
91impl<I: ExactSizeIterator> ExactSizeIterator for IdentifyLast<I> {
92 fn len(&self) -> usize { self.iter.len() }
93}
94
95#[derive(Debug, Clone)]
100pub struct IdentifyFirst<I: Iterator> {
101 is_first: bool,
102 iter: I,
103}
104
105impl<I: Iterator> Iterator for IdentifyFirst<I> {
106 type Item = (bool, I::Item);
107
108 fn next(&mut self) -> Option<Self::Item> {
109 if let Some(item) = self.iter.next() {
110 let is_first = replace(&mut self.is_first, false);
111 Some((is_first, item))
112 } else {
113 self.is_first = true;
114 None
115 }
116 }
117
118 fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
119}
120
121#[cfg(feature="nightly")]
122unsafe impl<I: TrustedLen> TrustedLen for IdentifyFirst<I> { }
123
124impl<I: ExactSizeIterator> ExactSizeIterator for IdentifyFirst<I> {
125 fn len(&self) -> usize { self.iter.len() }
126}
127
128impl<I: FusedIterator> FusedIterator for IdentifyFirst<I> { }
129
130pub trait IteratorIdentifyFirstLastExt: Iterator + Sized {
132 fn identify_first(self) -> IdentifyFirst<Self>;
138
139 fn identify_last(self) -> IdentifyLast<Self>;
145
146 fn identify_first_last(self) -> IdentifyFirstLast<Self>;
153}
154
155impl<I: Iterator + Sized> IteratorIdentifyFirstLastExt for I {
156 fn identify_first(self) -> IdentifyFirst<Self> { IdentifyFirst { is_first: true, iter: self } }
157
158 fn identify_last(self) -> IdentifyLast<Self> { IdentifyLast { iter: self.peekable() } }
159
160 fn identify_first_last(self) -> IdentifyFirstLast<Self> {
161 IdentifyFirstLast(self.identify_last().identify_first().map(
162 |(is_first, (is_last, item))| (is_first, is_last, item)
163 ))
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use arrayvec::ArrayVec;
170 use crate::IteratorIdentifyFirstLastExt;
171
172 #[test]
173 fn identify_first() {
174 assert_eq!(
175 [1, 2, 3, 4].into_iter().identify_first().collect::<ArrayVec<_, 4>>().as_slice(),
176 &[(true, 1), (false, 2), (false, 3), (false, 4)]
177 );
178 }
179
180 #[test]
181 fn identify_last() {
182 assert_eq!(
183 [1, 2, 3, 4].into_iter().identify_last().collect::<ArrayVec<_, 4>>().as_slice(),
184 &[(false, 1), (false, 2), (false, 3), (true, 4)]
185 );
186 }
187
188 #[test]
189 fn identify_first_last() {
190 assert_eq!(
191 [1, 2, 3, 4].into_iter().identify_first_last().collect::<ArrayVec<_, 4>>().as_slice(),
192 &[(true, false, 1), (false, false, 2), (false, false, 3), (false, true, 4)]
193 );
194 }
195}