[][src]Trait iterpipes::Pipe

pub trait Pipe {
    type InputItem;
    type OutputItem;
    fn next(&mut self, item: Self::InputItem) -> Self::OutputItem;

    fn bypass(self) -> Bypass<Self>
    where
        Self: Sized,
        Self::InputItem: Clone
, { ... }
fn compose(self) -> Composed<Self>
    where
        Self: Sized
, { ... }
fn connect<O: Pipe<InputItem = Self::OutputItem>>(
        self,
        other: O
    ) -> Connector<Self, O>
    where
        Self: Sized
, { ... }
fn into_iter(self) -> IterPipe<Self>
    where
        Self::InputItem: Default,
        Self: Sized + Pipe<InputItem = ()>
, { ... }
fn optional(self) -> Optional<Self>
    where
        Self: Sized
, { ... }
fn enumerate(self) -> Enumerate<Self>
    where
        Self: Sized
, { ... }
fn boxed(
        self
    ) -> Box<dyn Pipe<InputItem = Self::InputItem, OutputItem = Self::OutputItem>>
    where
        Self: Sized + 'static
, { ... } }

An iterator-style pipe.

For more general information about pipes, please see the module-level documentation.

Associated Types

type InputItem

The type of input this pipe accepts.

type OutputItem

The type of output this pipe produces.

Loading content...

Required methods

fn next(&mut self, item: Self::InputItem) -> Self::OutputItem

Calculate the next output item, based on an input item.

Loading content...

Provided methods

fn bypass(self) -> Bypass<Self> where
    Self: Sized,
    Self::InputItem: Clone

Create a bypassed version of the pipe.

The returned pipe clones the input item, calculates the next output item and returns both the copied input item and the output item.

Example

use iterpipes::*;

/// A pipe that rounds a floating point value to the nearest integer.
struct Round;

impl Pipe for Round {
    type InputItem = f32;
    type OutputItem = i32;

    fn next(&mut self, input: f32) -> i32 {
        input.round() as i32
    }
}

let mut pipe = Round {}.bypass();
assert_eq!((0.5, 1), pipe.next(0.5));
assert_eq!((-2.2, -2), pipe.next(-2.2));

fn compose(self) -> Composed<Self> where
    Self: Sized

Create a composable pipe.

Composable pipes implement the >> operator that concatenates pipes.

Example

use iterpipes::*;

/// A pipe that turns an index into a periodic progress value between 0.0 and 1.0.
struct Progress {
    period_length: usize,
}

impl Pipe for Progress {
    type InputItem = usize;
    type OutputItem = f32;

    fn next(&mut self, index: usize) -> f32 {
        (index % self.period_length) as f32 / self.period_length as f32
    }
}

/// A pipe that turns a progress value into a square wave.
struct SquareWave;

impl Pipe for SquareWave {
    type InputItem = f32;
    type OutputItem = f32;

    fn next(&mut self, progress: f32) -> f32 {
        if progress < 0.5 {
            -1.0
        } else {
            1.0
        }
    }
}

let mut pipe = PipeIter::new(0..).compose()
    >> Lazy::new(|i: Option<usize>| i.unwrap())
    >> Progress {period_length: 4}.compose()
    >> SquareWave;

for frame in &[-1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0] {
    assert_eq!(*frame, pipe.next(()));
}

A technical note

The Compose struct is a workaround the fact that this crate can not implement the Shr trait (the >> operator) for every type that implements Pipe since Shr isn't a part of this crate. This patttern is known as the newtype pattern.

fn connect<O: Pipe<InputItem = Self::OutputItem>>(
    self,
    other: O
) -> Connector<Self, O> where
    Self: Sized

Connect two pipes.

The created pipe takes an input item for self, calculates the intermediate value and then uses it to calculate the output value of the other pipe.

Obviously, the InputItem of self and the OutputItem of the other pipe have to match!

Example

use iterpipes::*;

/// A pipe that turns an index into a periodic progress value between 0.0 and 1.0.
struct Progress {
    period_length: usize,
}

impl Pipe for Progress {
    type InputItem = usize;
    type OutputItem = f32;

    fn next(&mut self, index: usize) -> f32 {
        (index % self.period_length) as f32 / self.period_length as f32
    }
}

/// A pipe that turns a progress value into a square wave.
struct SquareWave;

impl Pipe for SquareWave {
    type InputItem = f32;
    type OutputItem = f32;

    fn next(&mut self, progress: f32) -> f32 {
        if progress < 0.5 {
            -1.0
        } else {
            1.0
        }
    }
}

let mut pipe = Progress {period_length: 4}.connect(SquareWave);

for (index, frame) in [-1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0].iter().enumerate() {
    assert_eq!(*frame, pipe.next(index));
}

fn into_iter(self) -> IterPipe<Self> where
    Self::InputItem: Default,
    Self: Sized + Pipe<InputItem = ()>, 

Wrap the pipe into an iterator.

For example, this can be used to iterate over a pipeline in a for loop. The input item needs to have a default value, since the iterator has to create it on it's own, and the output item must be an Optional value.

Example

use iterpipes::*;

/// An pipe/iterator over a slice.
struct SlicePipe<'a, T> {
    data: &'a [T],
    index: usize,
}

impl<'a, T> Pipe for SlicePipe<'a, T> {
    type InputItem = ();
    type OutputItem = Option<&'a T>;

    fn next(&mut self, _: ()) -> Option<&'a T> {
        let value = self.data.get(self.index);
        if value.is_some() {
            self.index += 1;
        }
        value
    }
}

const DATA: &[u32] = &[3, 2, 1];
for (index, value) in (SlicePipe {data: DATA, index: 0}).into_iter().enumerate() {
    assert_eq!(DATA[index], *value);
}

fn optional(self) -> Optional<Self> where
    Self: Sized

Optionalize the pipe.

The decorated pipe's input and output items are the optional versions of the original input and output items. If an input item is fed into the decorated pipe, it returns some output value, but if None is fed into the decorated pipe, None is returned.

Example

use iterpipes::*;

/// A pipe that multiplies an input item by a factor.
struct Multiply<T>
where
    T: std::ops::Mul<T> + Copy
{
    factor: T,
}

impl<T> Pipe for Multiply<T>
where
    T: std::ops::Mul<T> + Copy
{
    type InputItem = T;
    type OutputItem = T::Output;

    fn next(&mut self, item: T) -> T::Output {
        item * self.factor
    }
}

let mut pipe = Multiply::<u32> { factor: 2 }.optional();

assert_eq!(Some(4), pipe.next(Some(2)));
assert_eq!(None, pipe.next(None));

fn enumerate(self) -> Enumerate<Self> where
    Self: Sized

Enumerate the output items of a pipe.

The decorated pipe will return a tuple of an index and the output item. The index starts from 0 and is counted up for every output item.

Example

use iterpipes::*;

/// A pipe that always returns a clone of the same value.
struct DefaultPipe<T: Clone> {
    value: T,
}

impl<T: Clone> Pipe for DefaultPipe<T> {
    type InputItem = ();
    type OutputItem = T;

    fn next(&mut self, _: ()) -> T {
        self.value.clone()
    }
}

let mut pipe = DefaultPipe { value: 42u8 }.enumerate();
assert_eq!((0, 42), pipe.next(()));
assert_eq!((1, 42), pipe.next(()));
assert_eq!((2, 42), pipe.next(()));

fn boxed(
    self
) -> Box<dyn Pipe<InputItem = Self::InputItem, OutputItem = Self::OutputItem>> where
    Self: Sized + 'static, 

Create a boxed trait object of the pipe.

This might be useful to move pipes across API bounds since it hides the internal composition of the pipe.

Example

use iterpipes::*;

fn create_pipe() -> Box<dyn Pipe<InputItem = usize, OutputItem = usize>> {
    Lazy::new(|i| i * 2).boxed()
}

let mut pipe = create_pipe();

for i in 0..4 {
    assert_eq!(i*2, pipe.next(i));
}
Loading content...

Implementations on Foreign Types

impl Pipe for ()[src]

type InputItem = ()

type OutputItem = ()

impl<'a, P: Pipe + ?Sized> Pipe for &'a mut P[src]

type InputItem = P::InputItem

type OutputItem = P::OutputItem

impl<A: Pipe> Pipe for (A,)[src]

type InputItem = (A::InputItem,)

type OutputItem = (A::OutputItem,)

impl<A: Pipe, B: Pipe> Pipe for (A, B)[src]

type InputItem = (A::InputItem, B::InputItem)

type OutputItem = (A::OutputItem, B::OutputItem)

impl<A: Pipe, B: Pipe, C: Pipe> Pipe for (A, B, C)[src]

type InputItem = (A::InputItem, B::InputItem, C::InputItem)

type OutputItem = (A::OutputItem, B::OutputItem, C::OutputItem)

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe> Pipe for (A, B, C, D)[src]

type InputItem = (A::InputItem, B::InputItem, C::InputItem, D::InputItem)

type OutputItem = (A::OutputItem, B::OutputItem, C::OutputItem, D::OutputItem)

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe, E: Pipe> Pipe for (A, B, C, D, E)[src]

type InputItem = (A::InputItem, B::InputItem, C::InputItem, D::InputItem, E::InputItem)

type OutputItem = (A::OutputItem, B::OutputItem, C::OutputItem, D::OutputItem, E::OutputItem)

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe, E: Pipe, F: Pipe> Pipe for (A, B, C, D, E, F)[src]

type InputItem = (A::InputItem, B::InputItem, C::InputItem, D::InputItem, E::InputItem, F::InputItem)

type OutputItem = (A::OutputItem, B::OutputItem, C::OutputItem, D::OutputItem, E::OutputItem, F::OutputItem)

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe, E: Pipe, F: Pipe, G: Pipe> Pipe for (A, B, C, D, E, F, G)[src]

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe, E: Pipe, F: Pipe, G: Pipe, H: Pipe> Pipe for (A, B, C, D, E, F, G, H)[src]

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe, E: Pipe, F: Pipe, G: Pipe, H: Pipe, I: Pipe> Pipe for (A, B, C, D, E, F, G, H, I)[src]

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe, E: Pipe, F: Pipe, G: Pipe, H: Pipe, I: Pipe, J: Pipe> Pipe for (A, B, C, D, E, F, G, H, I, J)[src]

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe, E: Pipe, F: Pipe, G: Pipe, H: Pipe, I: Pipe, J: Pipe, K: Pipe> Pipe for (A, B, C, D, E, F, G, H, I, J, K)[src]

impl<A: Pipe, B: Pipe, C: Pipe, D: Pipe, E: Pipe, F: Pipe, G: Pipe, H: Pipe, I: Pipe, J: Pipe, K: Pipe, L: Pipe> Pipe for (A, B, C, D, E, F, G, H, I, J, K, L)[src]

Loading content...

Implementors

impl<I, O, F> Pipe for Lazy<I, O, F> where
    F: Fn(I) -> O, 
[src]

type InputItem = I

type OutputItem = O

impl<I, O, F> Pipe for LazyMut<I, O, F> where
    F: FnMut(I) -> O, 
[src]

type InputItem = I

type OutputItem = O

impl<I: Iterator> Pipe for PipeIter<I>[src]

type InputItem = ()

type OutputItem = Option<I::Item>

impl<P> Pipe for Bypass<P> where
    P: Pipe,
    P::InputItem: Clone
[src]

type InputItem = P::InputItem

type OutputItem = (P::InputItem, P::OutputItem)

impl<P> Pipe for Composed<P> where
    P: Pipe
[src]

type InputItem = P::InputItem

type OutputItem = P::OutputItem

impl<P> Pipe for Optional<P> where
    P: Pipe
[src]

type InputItem = Option<P::InputItem>

type OutputItem = Option<P::OutputItem>

impl<P0, P1> Pipe for Connector<P0, P1> where
    P0: Pipe,
    P1: Pipe<InputItem = P0::OutputItem>, 
[src]

type InputItem = P0::InputItem

type OutputItem = P1::OutputItem

impl<P: Pipe> Pipe for Enumerate<P>[src]

type InputItem = P::InputItem

type OutputItem = (usize, P::OutputItem)

impl<T> Pipe for Counter<T> where
    T: AddAssign<T> + Copy
[src]

type InputItem = ()

type OutputItem = T

impl<T> Pipe for Ditto<T>[src]

type InputItem = T

type OutputItem = T

Loading content...