1#[cfg(not(feature = "ferrocene_subset"))]
2use crate::iter::{FusedIterator, TrustedLen};
3use crate::num::NonZero;
4use crate::ops::Try;
5
6#[cfg_attr(not(feature = "ferrocene_subset"), derive(Clone, Debug))]
22#[must_use = "iterators are lazy and do nothing unless consumed"]
23#[stable(feature = "rust1", since = "1.0.0")]
24pub struct Chain<A, B> {
25 a: Option<A>,
34 b: Option<B>,
35}
36impl<A, B> Chain<A, B> {
37 pub(in super::super) fn new(a: A, b: B) -> Chain<A, B> {
38 Chain { a: Some(a), b: Some(b) }
39 }
40}
41
42#[cfg(not(feature = "ferrocene_subset"))]
65#[stable(feature = "iter_chain", since = "1.91.0")]
66pub fn chain<A, B>(a: A, b: B) -> Chain<A::IntoIter, B::IntoIter>
67where
68 A: IntoIterator,
69 B: IntoIterator<Item = A::Item>,
70{
71 Chain::new(a.into_iter(), b.into_iter())
72}
73
74#[stable(feature = "rust1", since = "1.0.0")]
75impl<A, B> Iterator for Chain<A, B>
76where
77 A: Iterator,
78 B: Iterator<Item = A::Item>,
79{
80 type Item = A::Item;
81
82 #[inline]
83 fn next(&mut self) -> Option<A::Item> {
84 and_then_or_clear(&mut self.a, Iterator::next).or_else(|| self.b.as_mut()?.next())
85 }
86
87 #[inline]
88 #[rustc_inherit_overflow_checks]
89 fn count(self) -> usize {
90 let a_count = match self.a {
91 Some(a) => a.count(),
92 None => 0,
93 };
94 let b_count = match self.b {
95 Some(b) => b.count(),
96 None => 0,
97 };
98 a_count + b_count
99 }
100
101 fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
102 where
103 Self: Sized,
104 F: FnMut(Acc, Self::Item) -> R,
105 R: Try<Output = Acc>,
106 {
107 if let Some(ref mut a) = self.a {
108 acc = a.try_fold(acc, &mut f)?;
109 self.a = None;
110 }
111 if let Some(ref mut b) = self.b {
112 acc = b.try_fold(acc, f)?;
113 }
115 try { acc }
116 }
117
118 fn fold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
119 where
120 F: FnMut(Acc, Self::Item) -> Acc,
121 {
122 if let Some(a) = self.a {
123 acc = a.fold(acc, &mut f);
124 }
125 if let Some(b) = self.b {
126 acc = b.fold(acc, f);
127 }
128 acc
129 }
130
131 #[inline]
132 fn advance_by(&mut self, mut n: usize) -> Result<(), NonZero<usize>> {
133 if let Some(ref mut a) = self.a {
134 n = match a.advance_by(n) {
135 Ok(()) => return Ok(()),
136 Err(k) => k.get(),
137 };
138 self.a = None;
139 }
140
141 if let Some(ref mut b) = self.b {
142 return b.advance_by(n);
143 }
145
146 NonZero::new(n).map_or(Ok(()), Err)
147 }
148
149 #[inline]
150 fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
151 if let Some(ref mut a) = self.a {
152 n = match a.advance_by(n) {
153 Ok(()) => match a.next() {
154 None => 0,
155 x => return x,
156 },
157 Err(k) => k.get(),
158 };
159
160 self.a = None;
161 }
162
163 self.b.as_mut()?.nth(n)
164 }
165
166 #[inline]
167 fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
168 where
169 P: FnMut(&Self::Item) -> bool,
170 {
171 and_then_or_clear(&mut self.a, |a| a.find(&mut predicate))
172 .or_else(|| self.b.as_mut()?.find(predicate))
173 }
174
175 #[inline]
176 fn last(self) -> Option<A::Item> {
177 let a_last = self.a.and_then(Iterator::last);
179 let b_last = self.b.and_then(Iterator::last);
180 b_last.or(a_last)
181 }
182
183 #[inline]
184 fn size_hint(&self) -> (usize, Option<usize>) {
185 match self {
186 Chain { a: Some(a), b: Some(b) } => {
187 let (a_lower, a_upper) = a.size_hint();
188 let (b_lower, b_upper) = b.size_hint();
189
190 let lower = a_lower.saturating_add(b_lower);
191
192 let upper = match (a_upper, b_upper) {
193 (Some(x), Some(y)) => x.checked_add(y),
194 _ => None,
195 };
196
197 (lower, upper)
198 }
199 Chain { a: Some(a), b: None } => a.size_hint(),
200 Chain { a: None, b: Some(b) } => b.size_hint(),
201 Chain { a: None, b: None } => (0, Some(0)),
202 }
203 }
204}
205
206#[cfg(not(feature = "ferrocene_subset"))]
207#[stable(feature = "rust1", since = "1.0.0")]
208impl<A, B> DoubleEndedIterator for Chain<A, B>
209where
210 A: DoubleEndedIterator,
211 B: DoubleEndedIterator<Item = A::Item>,
212{
213 #[inline]
214 fn next_back(&mut self) -> Option<A::Item> {
215 and_then_or_clear(&mut self.b, |b| b.next_back()).or_else(|| self.a.as_mut()?.next_back())
216 }
217
218 #[inline]
219 fn advance_back_by(&mut self, mut n: usize) -> Result<(), NonZero<usize>> {
220 if let Some(ref mut b) = self.b {
221 n = match b.advance_back_by(n) {
222 Ok(()) => return Ok(()),
223 Err(k) => k.get(),
224 };
225 self.b = None;
226 }
227
228 if let Some(ref mut a) = self.a {
229 return a.advance_back_by(n);
230 }
232
233 NonZero::new(n).map_or(Ok(()), Err)
234 }
235
236 #[inline]
237 fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
238 if let Some(ref mut b) = self.b {
239 n = match b.advance_back_by(n) {
240 Ok(()) => match b.next_back() {
241 None => 0,
242 x => return x,
243 },
244 Err(k) => k.get(),
245 };
246
247 self.b = None;
248 }
249
250 self.a.as_mut()?.nth_back(n)
251 }
252
253 #[inline]
254 fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
255 where
256 P: FnMut(&Self::Item) -> bool,
257 {
258 and_then_or_clear(&mut self.b, |b| b.rfind(&mut predicate))
259 .or_else(|| self.a.as_mut()?.rfind(predicate))
260 }
261
262 fn try_rfold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
263 where
264 Self: Sized,
265 F: FnMut(Acc, Self::Item) -> R,
266 R: Try<Output = Acc>,
267 {
268 if let Some(ref mut b) = self.b {
269 acc = b.try_rfold(acc, &mut f)?;
270 self.b = None;
271 }
272 if let Some(ref mut a) = self.a {
273 acc = a.try_rfold(acc, f)?;
274 }
276 try { acc }
277 }
278
279 fn rfold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
280 where
281 F: FnMut(Acc, Self::Item) -> Acc,
282 {
283 if let Some(b) = self.b {
284 acc = b.rfold(acc, &mut f);
285 }
286 if let Some(a) = self.a {
287 acc = a.rfold(acc, f);
288 }
289 acc
290 }
291}
292
293#[cfg(not(feature = "ferrocene_subset"))]
295#[stable(feature = "fused", since = "1.26.0")]
296impl<A, B> FusedIterator for Chain<A, B>
297where
298 A: FusedIterator,
299 B: FusedIterator<Item = A::Item>,
300{
301}
302
303#[cfg(not(feature = "ferrocene_subset"))]
304#[unstable(feature = "trusted_len", issue = "37572")]
305unsafe impl<A, B> TrustedLen for Chain<A, B>
306where
307 A: TrustedLen,
308 B: TrustedLen<Item = A::Item>,
309{
310}
311
312#[cfg(not(feature = "ferrocene_subset"))]
313#[stable(feature = "default_iters", since = "1.70.0")]
314impl<A: Default, B: Default> Default for Chain<A, B> {
315 fn default() -> Self {
332 Chain::new(Default::default(), Default::default())
333 }
334}
335
336#[inline]
337fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option<U>) -> Option<U> {
338 let x = f(opt.as_mut()?);
339 if x.is_none() {
340 *opt = None;
341 }
342 x
343}