use crate::{Pipe, ResetablePipe};
use std::marker::PhantomData;
pub struct Connector<P0, P1>
where
P0: Pipe,
P1: Pipe<InputItem = P0::OutputItem>,
{
pipe0: P0,
pipe1: P1,
}
impl<P0, P1> Connector<P0, P1>
where
P0: Pipe,
P1: Pipe<InputItem = P0::OutputItem>,
{
pub fn new(pipe0: P0, pipe1: P1) -> Self {
Connector { pipe0, pipe1 }
}
}
impl<P0, P1> Pipe for Connector<P0, P1>
where
P0: Pipe,
P1: Pipe<InputItem = P0::OutputItem>,
{
type InputItem = P0::InputItem;
type OutputItem = P1::OutputItem;
fn next(&mut self, input: Self::InputItem) -> Self::OutputItem {
self.pipe1.next(self.pipe0.next(input))
}
}
impl<P0, P1> ResetablePipe for Connector<P0, P1>
where
P0: ResetablePipe,
P1: ResetablePipe<InputItem = P0::OutputItem>,
{
fn reset(&mut self) {
self.pipe0.reset();
self.pipe1.reset();
}
}
pub struct Bypass<P>
where
P: Pipe,
P::InputItem: Clone,
{
pipe: P,
}
impl<P> Bypass<P>
where
P: Pipe,
P::InputItem: Clone,
{
pub fn new(pipe: P) -> Self {
Self { pipe }
}
}
impl<P> Pipe for Bypass<P>
where
P: Pipe,
P::InputItem: Clone,
{
type InputItem = P::InputItem;
type OutputItem = (P::InputItem, P::OutputItem);
fn next(&mut self, input: P::InputItem) -> (P::InputItem, P::OutputItem) {
(input.clone(), self.pipe.next(input))
}
}
impl<P> ResetablePipe for Bypass<P>
where
P: ResetablePipe,
P::InputItem: Clone,
{
fn reset(&mut self) {
self.pipe.reset();
}
}
pub struct LazyMut<I, O, F>
where
F: FnMut(I) -> O,
{
function: F,
input: PhantomData<I>,
output: PhantomData<O>,
}
impl<I, O, F> LazyMut<I, O, F>
where
F: FnMut(I) -> O,
{
pub fn new(function: F) -> Self {
LazyMut {
function,
input: PhantomData,
output: PhantomData,
}
}
}
impl<I, O, F> Pipe for LazyMut<I, O, F>
where
F: FnMut(I) -> O,
{
type InputItem = I;
type OutputItem = O;
fn next(&mut self, input: I) -> O {
(self.function)(input)
}
}
pub struct Lazy<I, O, F>
where
F: Fn(I) -> O,
{
function: F,
input: PhantomData<I>,
output: PhantomData<O>,
}
impl<I, O, F> Lazy<I, O, F>
where
F: Fn(I) -> O,
{
pub fn new(function: F) -> Self {
Lazy {
function,
input: PhantomData,
output: PhantomData,
}
}
}
impl<I, O, F> Pipe for Lazy<I, O, F>
where
F: Fn(I) -> O,
{
type InputItem = I;
type OutputItem = O;
fn next(&mut self, input: I) -> O {
(self.function)(input)
}
}
impl<I, O, F> ResetablePipe for Lazy<I, O, F>
where
F: Fn(I) -> O,
{
fn reset(&mut self) {}
}
pub struct Optional<P>
where
P: Pipe,
{
pipe: P,
}
impl<P: Pipe> Optional<P> {
pub fn new(pipe: P) -> Self {
Optional { pipe }
}
}
impl<P> Pipe for Optional<P>
where
P: Pipe,
{
type InputItem = Option<P::InputItem>;
type OutputItem = Option<P::OutputItem>;
fn next(&mut self, item: Option<P::InputItem>) -> Option<P::OutputItem> {
item.map(|item| self.pipe.next(item))
}
}
impl<P> ResetablePipe for Optional<P>
where
P: ResetablePipe,
{
fn reset(&mut self) {
self.pipe.reset();
}
}
pub struct Enumerate<P>
where
P: Pipe,
{
pipe: P,
progress: usize,
}
impl<P: Pipe> Enumerate<P> {
pub fn new(pipe: P) -> Self {
Enumerate { pipe, progress: 0 }
}
}
impl<P: Pipe> Pipe for Enumerate<P> {
type InputItem = P::InputItem;
type OutputItem = (usize, P::OutputItem);
fn next(&mut self, item: P::InputItem) -> (usize, P::OutputItem) {
let next_item = self.pipe.next(item);
let index = self.progress;
self.progress += 1;
(index, next_item)
}
}
impl<P: ResetablePipe> ResetablePipe for Enumerate<P> {
fn reset(&mut self) {
self.pipe.reset();
self.progress = 0;
}
}
pub struct Counter<T>
where
T: std::ops::AddAssign<T> + Copy,
{
starting_value: T,
delta: T,
counter: T,
}
impl<T> Counter<T>
where
T: std::ops::AddAssign<T> + Copy,
{
pub fn new(starting_value: T, delta: T) -> Self {
Self {
starting_value,
delta,
counter: starting_value,
}
}
}
impl<T> Pipe for Counter<T>
where
T: std::ops::AddAssign<T> + Copy,
{
type InputItem = ();
type OutputItem = T;
fn next(&mut self, _: ()) -> T {
let item = self.counter;
self.counter += self.delta;
item
}
}
impl<T> ResetablePipe for Counter<T>
where
T: std::ops::AddAssign<T> + Copy,
{
fn reset(&mut self) {
self.counter = self.starting_value;
}
}
pub struct Ditto<T> {
item: PhantomData<T>,
}
impl<T> Default for Ditto<T> {
fn default() -> Self {
Self { item: PhantomData }
}
}
impl<T> Pipe for Ditto<T> {
type InputItem = T;
type OutputItem = T;
fn next(&mut self, item: T) -> T {
item
}
}
impl<T> ResetablePipe for Ditto<T> {
fn reset(&mut self) {}
}