Skip to content

Commit 8e7b44a

Browse files
authored
Merge pull request #15 from Palladinium/chain
Add chain
2 parents 605a279 + 111dd6f commit 8e7b44a

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

src/lib.rs

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,20 @@ pub trait StreamingIterator {
120120
self
121121
}
122122

123+
/// Consumes two iterators and returns a new iterator that iterates over both in sequence.
124+
#[inline]
125+
fn chain<I>(self, other: I) -> Chain<Self, I>
126+
where
127+
Self: Sized,
128+
I: StreamingIterator<Item = Self::Item> + Sized,
129+
{
130+
Chain {
131+
a: self,
132+
b: other,
133+
state: ChainState::BothForward,
134+
}
135+
}
136+
123137
/// Produces a normal, non-streaming, iterator by cloning the elements of this iterator.
124138
#[inline]
125139
fn cloned(self) -> Cloned<Self>
@@ -534,6 +548,86 @@ pub fn empty<I>() -> Empty<I> {
534548
}
535549
}
536550

551+
/// A streaming iterator that concatenates two streaming iterators
552+
#[derive(Debug)]
553+
pub struct Chain<A, B> {
554+
a: A,
555+
b: B,
556+
state: ChainState,
557+
}
558+
559+
#[derive(Debug)]
560+
enum ChainState {
561+
// Both iterators have items remaining and we are iterating forward
562+
BothForward,
563+
// Both iterators have items remaining and we are iterating backward
564+
BothBackward,
565+
// Only the front iterator has items
566+
Front,
567+
// Only the back iterator has items
568+
Back,
569+
}
570+
571+
impl<A, B> StreamingIterator for Chain<A, B>
572+
where
573+
A: StreamingIterator,
574+
B: StreamingIterator<Item = A::Item>,
575+
{
576+
type Item = A::Item;
577+
578+
#[inline]
579+
fn advance(&mut self) {
580+
use ChainState::*;
581+
582+
match self.state {
583+
BothForward | BothBackward => {
584+
self.state = if self.a.next().is_none() {
585+
self.b.advance();
586+
Back
587+
} else {
588+
BothForward
589+
};
590+
}
591+
Front => self.a.advance(),
592+
Back => self.b.advance(),
593+
}
594+
}
595+
596+
#[inline]
597+
fn get(&self) -> Option<&Self::Item> {
598+
use ChainState::*;
599+
600+
match self.state {
601+
BothForward | Front => self.a.get(),
602+
BothBackward | Back => self.b.get(),
603+
}
604+
}
605+
}
606+
607+
impl<A, B> DoubleEndedStreamingIterator for Chain<A, B>
608+
where
609+
A: DoubleEndedStreamingIterator,
610+
B: DoubleEndedStreamingIterator<Item = A::Item>,
611+
{
612+
#[inline]
613+
fn advance_back(&mut self) {
614+
use ChainState::*;
615+
616+
match self.state {
617+
BothForward | BothBackward => {
618+
self.state = if self.b.next_back().is_none() {
619+
self.a.advance_back();
620+
Front
621+
} else {
622+
BothBackward
623+
};
624+
}
625+
Front => self.a.advance_back(),
626+
Back => self.b.advance_back(),
627+
}
628+
}
629+
}
630+
537631
/// A normal, non-streaming, iterator which converts the elements of a streaming iterator into owned
538632
/// values by cloning them.
539633
#[derive(Clone, Debug)]
@@ -1502,6 +1596,21 @@ mod test {
15021596
assert_eq!(it.get(), None);
15031597
}
15041598

1599+
fn test_back<I>(mut it: I, expected: &[I::Item])
1600+
where
1601+
I: DoubleEndedStreamingIterator,
1602+
I::Item: Sized + PartialEq + Debug,
1603+
{
1604+
for item in expected {
1605+
it.advance_back();
1606+
assert_eq!(it.get(), Some(item));
1607+
assert_eq!(it.get(), Some(item));
1608+
}
1609+
it.advance_back();
1610+
assert_eq!(it.get(), None);
1611+
assert_eq!(it.get(), None);
1612+
}
1613+
15051614
#[test]
15061615
fn all() {
15071616
let items = [0, 1, 2];
@@ -1518,6 +1627,50 @@ mod test {
15181627
assert!(!it.clone().any(|&i| i > 2));
15191628
}
15201629

1630+
#[test]
1631+
fn test_chain() {
1632+
let items_a = [0, 1, 2, 3];
1633+
let items_b = [10, 20, 30];
1634+
let expected = [0, 1, 2, 3, 10, 20, 30];
1635+
1636+
let it = convert(items_a.iter().cloned()).chain(convert(items_b.iter().cloned()));
1637+
test(it, &expected);
1638+
}
1639+
1640+
#[test]
1641+
fn test_chain_back() {
1642+
let items_a = [0, 1, 2, 3];
1643+
let items_b = [10, 20, 30];
1644+
let expected = [30, 20, 10, 3, 2, 1, 0];
1645+
1646+
let it = convert(items_a.iter().cloned()).chain(convert(items_b.iter().cloned()));
1647+
test_back(it, &expected);
1648+
}
1649+
1650+
#[test]
1651+
fn test_chain_mixed() {
1652+
let items_a = [0, 1, 2, 3];
1653+
let items_b = [10, 20, 30];
1654+
1655+
let mut it = convert(items_a.iter().cloned()).chain(convert(items_b.iter().cloned()));
1656+
1657+
assert_eq!(it.get(), None);
1658+
it.advance();
1659+
assert_eq!(it.get().cloned(), Some(0));
1660+
it.advance_back();
1661+
assert_eq!(it.get().cloned(), Some(30));
1662+
it.advance();
1663+
assert_eq!(it.get().cloned(), Some(1));
1664+
it.advance_back();
1665+
assert_eq!(it.get().cloned(), Some(20));
1666+
it.advance();
1667+
assert_eq!(it.get().cloned(), Some(2));
1668+
it.advance_back();
1669+
assert_eq!(it.get().cloned(), Some(10));
1670+
it.advance_back();
1671+
assert_eq!(it.get().cloned(), Some(3));
1672+
}
1673+
15211674
#[test]
15221675
fn cloned() {
15231676
let items = [0, 1];

0 commit comments

Comments
 (0)