Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add map_with and fold_with #318

Merged
merged 1 commit into from
May 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/iter/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,95 @@ impl<'r, C, ID, F, T> Folder<T> for FoldFolder<'r, C, ID, F>
self.base.consume(self.item).complete()
}
}

// ///////////////////////////////////////////////////////////////////////////

pub fn fold_with<U, I, F>(base: I, item: U, fold_op: F) -> FoldWith<I, U, F>
where I: ParallelIterator,
F: Fn(U, I::Item) -> U + Sync,
U: Send + Clone
{
FoldWith {
base: base,
item: item,
fold_op: fold_op,
}
}

/// `FoldWith` is an iterator that applies a function over an iterator producing a single value.
/// This struct is created by the [`fold_with()`] method on [`ParallelIterator`]
///
/// [`fold_with()`]: trait.ParallelIterator.html#method.fold_with
/// [`ParallelIterator`]: trait.ParallelIterator.html
pub struct FoldWith<I, U, F> {
base: I,
item: U,
fold_op: F,
}

impl<U, I, F> ParallelIterator for FoldWith<I, U, F>
where I: ParallelIterator,
F: Fn(U, I::Item) -> U + Sync,
U: Send + Clone
{
type Item = U;

fn drive_unindexed<C>(self, consumer: C) -> C::Result
where C: UnindexedConsumer<Self::Item>
{
let consumer1 = FoldWithConsumer {
base: consumer,
item: self.item,
fold_op: &self.fold_op,
};
self.base.drive_unindexed(consumer1)
}
}

struct FoldWithConsumer<'c, C, U, F: 'c> {
base: C,
item: U,
fold_op: &'c F,
}

impl<'r, U, T, C, F> Consumer<T> for FoldWithConsumer<'r, C, U, F>
where C: Consumer<U>,
F: Fn(U, T) -> U + Sync,
U: Send + Clone
{
type Folder = FoldFolder<'r, C::Folder, U, F>;
type Reducer = C::Reducer;
type Result = C::Result;

fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
let (left, right, reducer) = self.base.split_at(index);
(FoldWithConsumer { base: left, item: self.item.clone(), ..self },
FoldWithConsumer { base: right, ..self }, reducer)
}

fn into_folder(self) -> Self::Folder {
FoldFolder {
base: self.base.into_folder(),
item: self.item,
fold_op: self.fold_op,
}
}

fn full(&self) -> bool {
self.base.full()
}
}

impl<'r, U, T, C, F> UnindexedConsumer<T> for FoldWithConsumer<'r, C, U, F>
where C: UnindexedConsumer<U>,
F: Fn(U, T) -> U + Sync,
U: Send + Clone
{
fn split_off_left(&self) -> Self {
FoldWithConsumer { base: self.base.split_off_left(), item: self.item.clone(), ..*self }
}

fn to_reducer(&self) -> Self::Reducer {
self.base.to_reducer()
}
}
296 changes: 296 additions & 0 deletions src/iter/map_with.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
use super::internal::*;
use super::*;


/// `MapWith` is an iterator that transforms the elements of an underlying iterator.
///
/// This struct is created by the [`map_with()`] method on [`ParallelIterator`]
///
/// [`map_with()`]: trait.ParallelIterator.html#method.map_with
/// [`ParallelIterator`]: trait.ParallelIterator.html
pub struct MapWith<I: ParallelIterator, T, F> {
base: I,
item: T,
map_op: F,
}

/// Create a new `MapWith` iterator.
///
/// NB: a free fn because it is NOT part of the end-user API.
pub fn new<I, T, F>(base: I, item: T, map_op: F) -> MapWith<I, T, F>
where I: ParallelIterator
{
MapWith {
base: base,
item: item,
map_op: map_op,
}
}

impl<I, T, F, R> ParallelIterator for MapWith<I, T, F>
where I: ParallelIterator,
T: Send + Clone,
F: Fn(&mut T, I::Item) -> R + Sync,
R: Send
{
type Item = R;

fn drive_unindexed<C>(self, consumer: C) -> C::Result
where C: UnindexedConsumer<Self::Item>
{
let consumer1 = MapWithConsumer::new(consumer, self.item, &self.map_op);
self.base.drive_unindexed(consumer1)
}

fn opt_len(&mut self) -> Option<usize> {
self.base.opt_len()
}
}

impl<I, T, F, R> IndexedParallelIterator for MapWith<I, T, F>
where I: IndexedParallelIterator,
T: Send + Clone,
F: Fn(&mut T, I::Item) -> R + Sync,
R: Send
{
fn drive<C>(self, consumer: C) -> C::Result
where C: Consumer<Self::Item>
{
let consumer1 = MapWithConsumer::new(consumer, self.item, &self.map_op);
self.base.drive(consumer1)
}

fn len(&mut self) -> usize {
self.base.len()
}

fn with_producer<CB>(self, callback: CB) -> CB::Output
where CB: ProducerCallback<Self::Item>
{
return self.base.with_producer(Callback {
callback: callback,
item: self.item,
map_op: self.map_op,
});

struct Callback<CB, U, F> {
callback: CB,
item: U,
map_op: F,
}

impl<T, U, F, R, CB> ProducerCallback<T> for Callback<CB, U, F>
where CB: ProducerCallback<R>,
U: Send + Clone,
F: Fn(&mut U, T) -> R + Sync,
R: Send
{
type Output = CB::Output;

fn callback<P>(self, base: P) -> CB::Output
where P: Producer<Item = T>
{
let producer = MapWithProducer {
base: base,
item: self.item,
map_op: &self.map_op,
};
self.callback.callback(producer)
}
}
}
}

/// ////////////////////////////////////////////////////////////////////////

struct MapWithProducer<'f, P, U, F: 'f> {
base: P,
item: U,
map_op: &'f F,
}

impl<'f, P, U, F, R> Producer for MapWithProducer<'f, P, U, F>
where P: Producer,
U: Send + Clone,
F: Fn(&mut U, P::Item) -> R + Sync,
R: Send
{
type Item = R;
type IntoIter = MapWithIter<'f, P::IntoIter, U, F>;

fn into_iter(self) -> Self::IntoIter {
MapWithIter {
base: self.base.into_iter(),
item: self.item,
map_op: self.map_op,
}
}

fn min_len(&self) -> usize {
self.base.min_len()
}
fn max_len(&self) -> usize {
self.base.max_len()
}

fn split_at(self, index: usize) -> (Self, Self) {
let (left, right) = self.base.split_at(index);
(MapWithProducer {
base: left,
item: self.item.clone(),
map_op: self.map_op,
},
MapWithProducer {
base: right,
item: self.item,
map_op: self.map_op,
})
}
}

struct MapWithIter<'f, I, U, F: 'f> {
base: I,
item: U,
map_op: &'f F,
}

impl<'f, I, U, F, R> Iterator for MapWithIter<'f, I, U, F>
where I: Iterator,
U: Send + Clone,
F: Fn(&mut U, I::Item) -> R + Sync,
R: Send
{
type Item = R;

fn next(&mut self) -> Option<R> {
self.base.next().map(|item| (self.map_op)(&mut self.item, item))
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.base.size_hint()
}
}

impl<'f, I, U, F, R> DoubleEndedIterator for MapWithIter<'f, I, U, F>
where I: DoubleEndedIterator,
U: Send + Clone,
F: Fn(&mut U, I::Item) -> R + Sync,
R: Send
{
fn next_back(&mut self) -> Option<R> {
self.base.next_back().map(|item| (self.map_op)(&mut self.item, item))
}
}

impl<'f, I, U, F, R> ExactSizeIterator for MapWithIter<'f, I, U, F>
where I: ExactSizeIterator,
U: Send + Clone,
F: Fn(&mut U, I::Item) -> R + Sync,
R: Send
{
}


/// ////////////////////////////////////////////////////////////////////////
/// Consumer implementation

struct MapWithConsumer<'f, C, U, F: 'f> {
base: C,
item: U,
map_op: &'f F,
}

impl<'f, C, U, F> MapWithConsumer<'f, C, U, F> {
fn new(base: C, item: U, map_op: &'f F) -> Self {
MapWithConsumer {
base: base,
item: item,
map_op: map_op,
}
}
}

impl<'f, T, U, R, C, F> Consumer<T> for MapWithConsumer<'f, C, U, F>
where C: Consumer<R>,
U: Send + Clone,
F: Fn(&mut U, T) -> R + Sync,
R: Send
{
type Folder = MapWithFolder<'f, C::Folder, U, F>;
type Reducer = C::Reducer;
type Result = C::Result;

fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
let (left, right, reducer) = self.base.split_at(index);
(MapWithConsumer::new(left, self.item.clone(), self.map_op),
MapWithConsumer::new(right, self.item, self.map_op),
reducer)
}

fn into_folder(self) -> Self::Folder {
MapWithFolder {
base: self.base.into_folder(),
item: self.item,
map_op: self.map_op,
}
}

fn full(&self) -> bool {
self.base.full()
}
}

impl<'f, T, U, R, C, F> UnindexedConsumer<T> for MapWithConsumer<'f, C, U, F>
where C: UnindexedConsumer<R>,
U: Send + Clone,
F: Fn(&mut U, T) -> R + Sync,
R: Send
{
fn split_off_left(&self) -> Self {
MapWithConsumer::new(self.base.split_off_left(), self.item.clone(), self.map_op)
}

fn to_reducer(&self) -> Self::Reducer {
self.base.to_reducer()
}
}

struct MapWithFolder<'f, C, U, F: 'f> {
base: C,
item: U,
map_op: &'f F,
}

impl<'f, T, U, R, C, F> Folder<T> for MapWithFolder<'f, C, U, F>
where C: Folder<R>,
U: Clone,
F: Fn(&mut U, T) -> R
{
type Result = C::Result;

fn consume(mut self, item: T) -> Self {
let mapped_item = (self.map_op)(&mut self.item, item);
self.base = self.base.consume(mapped_item);
self
}

fn consume_iter<I>(mut self, iter: I) -> Self
where I: IntoIterator<Item = T>
{
{
let map_op = self.map_op;
let item = &mut self.item;
let mapped_iter = iter.into_iter().map(|x| map_op(item, x));
self.base = self.base.consume_iter(mapped_iter);
}
self
}

fn complete(self) -> C::Result {
self.base.complete()
}

fn full(&self) -> bool {
self.base.full()
}
}
Loading