1use core::iter::FusedIterator;
4
5pub struct Bidi<I>
43where I: DoubleEndedIterator
44{
45 inner: I,
47 next: fn(&mut I) -> Option<<I as Iterator>::Item>,
49 next_back: fn(&mut I) -> Option<<I as Iterator>::Item>,
51 nth: fn(&mut I, usize) -> Option<<I as Iterator>::Item>,
53 nth_back: fn(&mut I, usize) -> Option<<I as Iterator>::Item>,
55}
56
57impl<I> Bidi<I>
58where I: DoubleEndedIterator
59{
60 pub fn new<II>(iter: II, cond: bool) -> Self
68 where II: IntoIterator<IntoIter = I> {
69 let inner = iter.into_iter();
70 if cond {
71 Self {
72 inner,
73 next: <I as DoubleEndedIterator>::next_back,
74 next_back: <I as Iterator>::next,
75 nth: <I as DoubleEndedIterator>::nth_back,
76 nth_back: <I as Iterator>::nth,
77 }
78 }
79 else {
80 Self {
81 inner,
82 next: <I as Iterator>::next,
83 next_back: <I as DoubleEndedIterator>::next_back,
84 nth: <I as Iterator>::nth,
85 nth_back: <I as DoubleEndedIterator>::nth_back,
86 }
87 }
88 }
89}
90
91impl<I> Iterator for Bidi<I>
92where I: DoubleEndedIterator
93{
94 type Item = <I as Iterator>::Item;
95
96 #[inline]
97 fn next(&mut self) -> Option<Self::Item> {
98 (&mut self.next)(&mut self.inner)
99 }
100
101 #[inline]
102 fn nth(&mut self, n: usize) -> Option<Self::Item> {
103 (&mut self.nth)(&mut self.inner, n)
104 }
105
106 #[inline]
107 #[cfg(not(tarpaulin_include))]
108 fn size_hint(&self) -> (usize, Option<usize>) {
109 self.inner.size_hint()
110 }
111
112 #[inline]
113 #[cfg(not(tarpaulin_include))]
114 fn count(self) -> usize {
115 self.inner.count()
116 }
117
118 #[inline]
119 #[cfg(not(tarpaulin_include))]
120 fn last(mut self) -> Option<Self::Item> {
121 self.next_back()
122 }
123}
124
125impl<I> DoubleEndedIterator for Bidi<I>
126where I: DoubleEndedIterator
127{
128 #[inline]
129 fn next_back(&mut self) -> Option<Self::Item> {
130 (&mut self.next_back)(&mut self.inner)
131 }
132
133 #[inline]
134 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
135 (&mut self.nth_back)(&mut self.inner, n)
136 }
137}
138
139impl<I> ExactSizeIterator for Bidi<I>
140where I: DoubleEndedIterator + ExactSizeIterator
141{
142 #[inline]
143 #[cfg(not(tarpaulin_include))]
144 fn len(&self) -> usize {
145 self.inner.len()
146 }
147}
148
149impl<I> FusedIterator for Bidi<I> where I: DoubleEndedIterator + FusedIterator
150{
151}
152
153pub trait BidiIterator
155where
156 Self: Sized + IntoIterator,
157 <Self as IntoIterator>::IntoIter: DoubleEndedIterator,
158{
159 fn bidi(self, cond: bool) -> Bidi<Self::IntoIter> {
180 Bidi::new(self, cond)
181 }
182}
183
184impl<I> BidiIterator for I
185where
186 I: Sized + IntoIterator,
187 <I as IntoIterator>::IntoIter: DoubleEndedIterator,
188{
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 #[test]
196 fn forward() {
197 let mut iter = (0 .. 6).bidi(false);
198
199 assert_eq!(iter.next(), Some(0));
200 assert_eq!(iter.next_back(), Some(5));
201 assert_eq!(iter.nth(1), Some(2));
202 assert_eq!(iter.nth_back(1), Some(3));
203 assert!(iter.next().is_none());
204 }
205
206 #[test]
207 fn reverse() {
208 let mut iter = (0 .. 6).bidi(true);
209
210 assert_eq!(iter.next(), Some(5));
211 assert_eq!(iter.next_back(), Some(0));
212 assert_eq!(iter.nth(1), Some(3));
213 assert_eq!(iter.nth_back(1), Some(2));
214 assert!(iter.next().is_none());
215 }
216}