Skip to content

Commit cf3aad7

Browse files
authored
Merge pull request #11 from Palladinium/map-deref
Add map_deref and filter_map_deref
2 parents 8c20653 + 15b467b commit cf3aad7

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

src/lib.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,16 @@ pub trait StreamingIterator {
193193
}
194194
}
195195

196+
/// Creates a regular, non-streaming iterator which both filters and maps by applying a closure to elements.
197+
#[inline]
198+
fn filter_map_deref<B, F>(self, f: F) -> FilterMapDeref<Self, F>
199+
where
200+
Self: Sized,
201+
F: FnMut(&Self::Item) -> Option<B>,
202+
{
203+
FilterMapDeref { it: self, f }
204+
}
205+
196206
/// Returns the first element of the iterator that satisfies the predicate.
197207
#[inline]
198208
fn find<F>(&mut self, mut f: F) -> Option<&Self::Item>
@@ -255,6 +265,16 @@ pub trait StreamingIterator {
255265
}
256266
}
257267

268+
/// Creates a regular, non-streaming iterator which transforms elements of this iterator by passing them to a closure.
269+
#[inline]
270+
fn map_deref<B, F>(self, f: F) -> MapDeref<Self, F>
271+
where
272+
Self: Sized,
273+
F: FnMut(&Self::Item) -> B,
274+
{
275+
MapDeref { it: self, f }
276+
}
277+
258278
/// Creates an iterator which transforms elements of this iterator by passing them to a closure.
259279
///
260280
/// Unlike `map`, this method takes a closure that returns a reference into the original value.
@@ -1013,6 +1033,49 @@ where
10131033
}
10141034
}
10151035

1036+
/// A regular, non-streaming iterator which both filters and maps elements of a streaming iterator with a closure.
1037+
#[derive(Debug)]
1038+
pub struct FilterMapDeref<I, F> {
1039+
it: I,
1040+
f: F,
1041+
}
1042+
1043+
impl<I, B, F> Iterator for FilterMapDeref<I, F>
1044+
where
1045+
I: StreamingIterator,
1046+
F: FnMut(&I::Item) -> Option<B>,
1047+
{
1048+
type Item = B;
1049+
1050+
#[inline]
1051+
fn next(&mut self) -> Option<Self::Item> {
1052+
while let Some(item) = self.it.next() {
1053+
if let Some(mapped) = (self.f)(item) {
1054+
return Some(mapped);
1055+
}
1056+
}
1057+
1058+
None
1059+
}
1060+
}
1061+
1062+
impl<I, B, F> DoubleEndedIterator for FilterMapDeref<I, F>
1063+
where
1064+
I: DoubleEndedStreamingIterator,
1065+
F: FnMut(&I::Item) -> Option<B>,
1066+
{
1067+
#[inline]
1068+
fn next_back(&mut self) -> Option<B> {
1069+
while let Some(item) = self.it.next_back() {
1070+
if let Some(mapped) = (self.f)(item) {
1071+
return Some(mapped);
1072+
}
1073+
}
1074+
1075+
None
1076+
}
1077+
}
1078+
10161079
#[derive(Copy, Clone, Debug)]
10171080
enum FuseState {
10181081
Start,
@@ -1213,6 +1276,42 @@ where
12131276
}
12141277
}
12151278

1279+
/// A regular, non-streaming iterator which transforms the elements of a streaming iterator.
1280+
#[derive(Debug)]
1281+
pub struct MapDeref<I, F> {
1282+
it: I,
1283+
f: F,
1284+
}
1285+
1286+
impl<I, B, F> Iterator for MapDeref<I, F>
1287+
where
1288+
I: StreamingIterator,
1289+
F: FnMut(&I::Item) -> B,
1290+
{
1291+
type Item = B;
1292+
1293+
#[inline]
1294+
fn next(&mut self) -> Option<Self::Item> {
1295+
self.it.next().map(&mut self.f)
1296+
}
1297+
1298+
#[inline]
1299+
fn size_hint(&self) -> (usize, Option<usize>) {
1300+
self.it.size_hint()
1301+
}
1302+
}
1303+
1304+
impl<I, B, F> DoubleEndedIterator for MapDeref<I, F>
1305+
where
1306+
I: DoubleEndedStreamingIterator,
1307+
F: FnMut(&I::Item) -> B,
1308+
{
1309+
#[inline]
1310+
fn next_back(&mut self) -> Option<Self::Item> {
1311+
self.it.next_back().map(&mut self.f)
1312+
}
1313+
}
1314+
12161315
/// A streaming iterator which transforms the elements of a streaming iterator.
12171316
#[derive(Debug)]
12181317
pub struct MapRef<I, F> {
@@ -1611,6 +1710,17 @@ mod test {
16111710
assert_eq!(it.get(), None);
16121711
}
16131712

1713+
fn test_deref<I>(mut it: I, expected: &[I::Item])
1714+
where
1715+
I: Iterator,
1716+
I::Item: Sized + PartialEq + Debug,
1717+
{
1718+
for item in expected {
1719+
assert_eq!(it.next().as_ref(), Some(item));
1720+
}
1721+
assert_eq!(it.next(), None)
1722+
}
1723+
16141724
#[test]
16151725
fn all() {
16161726
let items = [0, 1, 2];
@@ -1769,6 +1879,13 @@ mod test {
17691879
test(it, &items);
17701880
}
17711881

1882+
#[test]
1883+
fn map_deref() {
1884+
let items = [0, 1];
1885+
let it = convert(items.iter().map(|&i| i as usize)).map_deref(|&i| i as i32);
1886+
test_deref(it, &items);
1887+
}
1888+
17721889
#[test]
17731890
fn map_ref() {
17741891
#[derive(Clone)]
@@ -1803,6 +1920,14 @@ mod test {
18031920
test(it, &[0, 2, 4])
18041921
}
18051922

1923+
#[test]
1924+
fn filter_map_deref() {
1925+
let items = [0u8, 1, 1, 2, 4];
1926+
let it =
1927+
convert(items.iter()).filter_map_deref(|&&i| if i % 2 == 0 { Some(i) } else { None });
1928+
test_deref(it, &[0, 2, 4])
1929+
}
1930+
18061931
#[test]
18071932
fn find() {
18081933
let items = [0, 1];

0 commit comments

Comments
 (0)