From ebfd08312522b85a5b4085aa0a2bf6fb9b9873d7 Mon Sep 17 00:00:00 2001 From: Clar Fon Date: Mon, 17 Dec 2018 19:28:40 -0500 Subject: [PATCH] Move Chain and ChainState to own module --- src/libcore/iter/adapters/chain.rs | 255 +++++++++++++++++++++++++++++ src/libcore/iter/adapters/mod.rs | 254 +--------------------------- 2 files changed, 258 insertions(+), 251 deletions(-) create mode 100644 src/libcore/iter/adapters/chain.rs diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs new file mode 100644 index 000000000000..5defb857d50d --- /dev/null +++ b/src/libcore/iter/adapters/chain.rs @@ -0,0 +1,255 @@ +use ops::Try; +use usize; +use super::super::{Iterator, DoubleEndedIterator, FusedIterator, TrustedLen}; + +/// An iterator that strings two iterators together. +/// +/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`chain`]: trait.Iterator.html#method.chain +/// [`Iterator`]: trait.Iterator.html +#[derive(Clone, Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Chain { + pub(in super::super) a: A, + pub(in super::super) b: B, + pub(in super::super) state: ChainState, +} + +// The iterator protocol specifies that iteration ends with the return value +// `None` from `.next()` (or `.next_back()`) and it is unspecified what +// further calls return. The chain adaptor must account for this since it uses +// two subiterators. +// +// It uses three states: +// +// - Both: `a` and `b` are remaining +// - Front: `a` remaining +// - Back: `b` remaining +// +// The fourth state (neither iterator is remaining) only occurs after Chain has +// returned None once, so we don't need to store this state. +#[derive(Clone, Debug)] +pub(in super::super) enum ChainState { + // both front and back iterator are remaining + Both, + // only front is remaining + Front, + // only back is remaining + Back, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for Chain where + A: Iterator, + B: Iterator +{ + type Item = A::Item; + + #[inline] + fn next(&mut self) -> Option { + match self.state { + ChainState::Both => match self.a.next() { + elt @ Some(..) => elt, + None => { + self.state = ChainState::Back; + self.b.next() + } + }, + ChainState::Front => self.a.next(), + ChainState::Back => self.b.next(), + } + } + + #[inline] + #[rustc_inherit_overflow_checks] + fn count(self) -> usize { + match self.state { + ChainState::Both => self.a.count() + self.b.count(), + ChainState::Front => self.a.count(), + ChainState::Back => self.b.count(), + } + } + + fn try_fold(&mut self, init: Acc, mut f: F) -> R where + Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Front => { + accum = self.a.try_fold(accum, &mut f)?; + if let ChainState::Both = self.state { + self.state = ChainState::Back; + } + } + _ => { } + } + if let ChainState::Back = self.state { + accum = self.b.try_fold(accum, &mut f)?; + } + Try::from_ok(accum) + } + + fn fold(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Front => { + accum = self.a.fold(accum, &mut f); + } + _ => { } + } + match self.state { + ChainState::Both | ChainState::Back => { + accum = self.b.fold(accum, &mut f); + } + _ => { } + } + accum + } + + #[inline] + fn nth(&mut self, mut n: usize) -> Option { + match self.state { + ChainState::Both | ChainState::Front => { + for x in self.a.by_ref() { + if n == 0 { + return Some(x) + } + n -= 1; + } + if let ChainState::Both = self.state { + self.state = ChainState::Back; + } + } + ChainState::Back => {} + } + if let ChainState::Back = self.state { + self.b.nth(n) + } else { + None + } + } + + #[inline] + fn find

(&mut self, mut predicate: P) -> Option where + P: FnMut(&Self::Item) -> bool, + { + match self.state { + ChainState::Both => match self.a.find(&mut predicate) { + None => { + self.state = ChainState::Back; + self.b.find(predicate) + } + v => v + }, + ChainState::Front => self.a.find(predicate), + ChainState::Back => self.b.find(predicate), + } + } + + #[inline] + fn last(self) -> Option { + match self.state { + ChainState::Both => { + // Must exhaust a before b. + let a_last = self.a.last(); + let b_last = self.b.last(); + b_last.or(a_last) + }, + ChainState::Front => self.a.last(), + ChainState::Back => self.b.last() + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = a_lower.saturating_add(b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None + }; + + (lower, upper) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Chain where + A: DoubleEndedIterator, + B: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option { + match self.state { + ChainState::Both => match self.b.next_back() { + elt @ Some(..) => elt, + None => { + self.state = ChainState::Front; + self.a.next_back() + } + }, + ChainState::Front => self.a.next_back(), + ChainState::Back => self.b.next_back(), + } + } + + fn try_rfold(&mut self, init: Acc, mut f: F) -> R where + Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Back => { + accum = self.b.try_rfold(accum, &mut f)?; + if let ChainState::Both = self.state { + self.state = ChainState::Front; + } + } + _ => { } + } + if let ChainState::Front = self.state { + accum = self.a.try_rfold(accum, &mut f)?; + } + Try::from_ok(accum) + } + + fn rfold(self, init: Acc, mut f: F) -> Acc + where F: FnMut(Acc, Self::Item) -> Acc, + { + let mut accum = init; + match self.state { + ChainState::Both | ChainState::Back => { + accum = self.b.rfold(accum, &mut f); + } + _ => { } + } + match self.state { + ChainState::Both | ChainState::Front => { + accum = self.a.rfold(accum, &mut f); + } + _ => { } + } + accum + } + +} + +// Note: *both* must be fused to handle double-ended iterators. +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Chain + where A: FusedIterator, + B: FusedIterator, +{} + +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for Chain + where A: TrustedLen, B: TrustedLen, +{} + diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index f2bedf390e3b..67c7c7a0566d 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -6,9 +6,12 @@ use intrinsics; use super::{Iterator, DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen}; use super::LoopState; +mod chain; mod zip; +pub use self::chain::Chain; pub use self::zip::Zip; +pub(super) use self::chain::ChainState; pub(super) use self::zip::ZipImpl; pub(crate) use self::zip::TrustedRandomAccess; @@ -457,257 +460,6 @@ impl Iterator for StepBy where I: Iterator { #[stable(feature = "iterator_step_by", since = "1.28.0")] impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} -/// An iterator that strings two iterators together. -/// -/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its -/// documentation for more. -/// -/// [`chain`]: trait.Iterator.html#method.chain -/// [`Iterator`]: trait.Iterator.html -#[derive(Clone, Debug)] -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Chain { - pub(super) a: A, - pub(super) b: B, - pub(super) state: ChainState, -} - -// The iterator protocol specifies that iteration ends with the return value -// `None` from `.next()` (or `.next_back()`) and it is unspecified what -// further calls return. The chain adaptor must account for this since it uses -// two subiterators. -// -// It uses three states: -// -// - Both: `a` and `b` are remaining -// - Front: `a` remaining -// - Back: `b` remaining -// -// The fourth state (neither iterator is remaining) only occurs after Chain has -// returned None once, so we don't need to store this state. -#[derive(Clone, Debug)] -pub(super) enum ChainState { - // both front and back iterator are remaining - Both, - // only front is remaining - Front, - // only back is remaining - Back, -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Chain where - A: Iterator, - B: Iterator -{ - type Item = A::Item; - - #[inline] - fn next(&mut self) -> Option { - match self.state { - ChainState::Both => match self.a.next() { - elt @ Some(..) => elt, - None => { - self.state = ChainState::Back; - self.b.next() - } - }, - ChainState::Front => self.a.next(), - ChainState::Back => self.b.next(), - } - } - - #[inline] - #[rustc_inherit_overflow_checks] - fn count(self) -> usize { - match self.state { - ChainState::Both => self.a.count() + self.b.count(), - ChainState::Front => self.a.count(), - ChainState::Back => self.b.count(), - } - } - - fn try_fold(&mut self, init: Acc, mut f: F) -> R where - Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try - { - let mut accum = init; - match self.state { - ChainState::Both | ChainState::Front => { - accum = self.a.try_fold(accum, &mut f)?; - if let ChainState::Both = self.state { - self.state = ChainState::Back; - } - } - _ => { } - } - if let ChainState::Back = self.state { - accum = self.b.try_fold(accum, &mut f)?; - } - Try::from_ok(accum) - } - - fn fold(self, init: Acc, mut f: F) -> Acc - where F: FnMut(Acc, Self::Item) -> Acc, - { - let mut accum = init; - match self.state { - ChainState::Both | ChainState::Front => { - accum = self.a.fold(accum, &mut f); - } - _ => { } - } - match self.state { - ChainState::Both | ChainState::Back => { - accum = self.b.fold(accum, &mut f); - } - _ => { } - } - accum - } - - #[inline] - fn nth(&mut self, mut n: usize) -> Option { - match self.state { - ChainState::Both | ChainState::Front => { - for x in self.a.by_ref() { - if n == 0 { - return Some(x) - } - n -= 1; - } - if let ChainState::Both = self.state { - self.state = ChainState::Back; - } - } - ChainState::Back => {} - } - if let ChainState::Back = self.state { - self.b.nth(n) - } else { - None - } - } - - #[inline] - fn find

(&mut self, mut predicate: P) -> Option where - P: FnMut(&Self::Item) -> bool, - { - match self.state { - ChainState::Both => match self.a.find(&mut predicate) { - None => { - self.state = ChainState::Back; - self.b.find(predicate) - } - v => v - }, - ChainState::Front => self.a.find(predicate), - ChainState::Back => self.b.find(predicate), - } - } - - #[inline] - fn last(self) -> Option { - match self.state { - ChainState::Both => { - // Must exhaust a before b. - let a_last = self.a.last(); - let b_last = self.b.last(); - b_last.or(a_last) - }, - ChainState::Front => self.a.last(), - ChainState::Back => self.b.last() - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let (a_lower, a_upper) = self.a.size_hint(); - let (b_lower, b_upper) = self.b.size_hint(); - - let lower = a_lower.saturating_add(b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None - }; - - (lower, upper) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Chain where - A: DoubleEndedIterator, - B: DoubleEndedIterator, -{ - #[inline] - fn next_back(&mut self) -> Option { - match self.state { - ChainState::Both => match self.b.next_back() { - elt @ Some(..) => elt, - None => { - self.state = ChainState::Front; - self.a.next_back() - } - }, - ChainState::Front => self.a.next_back(), - ChainState::Back => self.b.next_back(), - } - } - - fn try_rfold(&mut self, init: Acc, mut f: F) -> R where - Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try - { - let mut accum = init; - match self.state { - ChainState::Both | ChainState::Back => { - accum = self.b.try_rfold(accum, &mut f)?; - if let ChainState::Both = self.state { - self.state = ChainState::Front; - } - } - _ => { } - } - if let ChainState::Front = self.state { - accum = self.a.try_rfold(accum, &mut f)?; - } - Try::from_ok(accum) - } - - fn rfold(self, init: Acc, mut f: F) -> Acc - where F: FnMut(Acc, Self::Item) -> Acc, - { - let mut accum = init; - match self.state { - ChainState::Both | ChainState::Back => { - accum = self.b.rfold(accum, &mut f); - } - _ => { } - } - match self.state { - ChainState::Both | ChainState::Front => { - accum = self.a.rfold(accum, &mut f); - } - _ => { } - } - accum - } - -} - -// Note: *both* must be fused to handle double-ended iterators. -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Chain - where A: FusedIterator, - B: FusedIterator, -{} - -#[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl TrustedLen for Chain - where A: TrustedLen, B: TrustedLen, -{} - /// An iterator that maps the values of `iter` with `f`. /// /// This `struct` is created by the [`map`] method on [`Iterator`]. See its