Skip to content

Commit b4c446d

Browse files
committed
Add fn successors and Successors
1 parent 3ee7aee commit b4c446d

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub use sources::{once, Once};
5454
pub use sources::{once_with, OnceWith};
5555
pub use sources::{repeat, Repeat};
5656
pub use sources::{repeat_with, RepeatWith};
57+
pub use sources::{successors, Successors};
5758

5859
/// An interface for dealing with streaming iterators.
5960
pub trait StreamingIterator {

src/sources.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ pub fn repeat_with<T, F: FnMut() -> T>(gen: F) -> RepeatWith<T, F> {
7979
RepeatWith { gen, item: None }
8080
}
8181

82+
/// Creates an iterator where each successive item is computed from the preceding one.
83+
#[inline]
84+
pub fn successors<T, F: FnMut(T) -> Option<T>>(first: Option<T>, succ: F) -> Successors<T, F> {
85+
Successors {
86+
first: true,
87+
item: first,
88+
succ,
89+
}
90+
}
91+
8292
/// A streaming iterator which yields elements from a normal, non-streaming, iterator.
8393
#[derive(Clone, Debug)]
8494
pub struct Convert<I>
@@ -387,3 +397,41 @@ impl<T, F: FnMut() -> T> StreamingIterator for RepeatWith<T, F> {
387397
(usize::MAX, None)
388398
}
389399
}
400+
401+
/// An iterator where each successive item is computed from the preceding one.
402+
#[derive(Clone, Debug)]
403+
pub struct Successors<T, F> {
404+
first: bool,
405+
item: Option<T>,
406+
succ: F,
407+
}
408+
409+
impl<T, F: FnMut(T) -> Option<T>> StreamingIterator for Successors<T, F> {
410+
type Item = T;
411+
412+
#[inline]
413+
fn advance(&mut self) {
414+
if self.first {
415+
self.first = false;
416+
} else if let Some(item) = self.item.take() {
417+
self.item = (self.succ)(item);
418+
}
419+
}
420+
421+
#[inline]
422+
fn get(&self) -> Option<&Self::Item> {
423+
self.item.as_ref()
424+
}
425+
426+
#[inline]
427+
fn size_hint(&self) -> (usize, Option<usize>) {
428+
match (self.first, &self.item) {
429+
// We have a first item and unknown successors
430+
(true, &Some(_)) => (1, None),
431+
// We only have unknown successors
432+
(false, &Some(_)) => (0, None),
433+
// We have nothing.
434+
(_, &None) => (0, Some(0)),
435+
}
436+
}
437+
}

0 commit comments

Comments
 (0)