use super::{Error, Sequence};
use crate::helpers::{WithHistory, WithLastValue};
use std::fmt;
type BoxedFnMethod<'a, M> = Box<dyn FnMut(&'a <M as Method>::Input) -> <M as Method>::Output>;
pub trait Method {
type Params;
type Input: ?Sized;
type Output;
fn new(parameters: Self::Params, initial_value: &Self::Input) -> Result<Self, Error>
where
Self: Sized;
fn next(&mut self, value: &Self::Input) -> Self::Output;
fn with_history(
parameters: Self::Params,
initial_value: &Self::Input,
) -> Result<WithHistory<Self, Self::Output>, Error>
where
Self: Sized,
Self::Output: fmt::Debug + Clone,
{
WithHistory::new(parameters, initial_value)
}
fn with_last_value(
parameters: Self::Params,
initial_value: &Self::Input,
) -> Result<WithLastValue<Self, Self::Output>, Error>
where
Self: Sized,
Self::Output: fmt::Debug + Clone,
{
WithLastValue::new(parameters, initial_value)
}
fn name(&self) -> &str {
let parts = std::any::type_name::<Self>().split("::");
parts.last().unwrap_or_default()
}
#[deprecated]
fn memsize(&self) -> (usize, usize)
where
Self: Sized,
{
(std::mem::size_of::<Self>(), std::mem::align_of::<Self>())
}
#[inline]
fn over<S>(&mut self, inputs: S) -> Vec<Self::Output>
where
S: Sequence<Self::Input>,
Self::Input: Sized,
Self: Sized,
{
inputs.call(self)
}
fn apply<T, S>(&mut self, sequence: &mut S)
where
S: Sequence<T> + AsMut<[T]> + ?Sized,
Self: Method<Input = T, Output = T> + Sized,
{
sequence.apply(self);
}
fn new_over<S>(parameters: Self::Params, inputs: S) -> Result<Vec<Self::Output>, Error>
where
S: Sequence<Self::Input>,
Self::Input: Sized,
Self: Sized,
{
match inputs.get_initial_value() {
Some(v) => {
let mut method = Self::new(parameters, v)?;
Ok(inputs.call(&mut method))
}
None => Ok(Vec::new()),
}
}
fn new_apply<T, S>(parameters: Self::Params, sequence: &mut S) -> Result<(), Error>
where
S: Sequence<T> + AsMut<[T]>,
Self: Method<Input = T, Output = T> + Sized,
{
let initial_value = {
let seq = &*sequence;
match seq.get_initial_value() {
Some(v) => v,
None => return Ok(()),
}
};
let mut m = Self::new(parameters, initial_value)?;
sequence.apply(&mut m);
Ok(())
}
fn into_fn<'a>(mut self) -> BoxedFnMethod<'a, Self>
where
Self: Sized + 'static,
Self::Input: 'static,
{
let f = move |x| self.next(x);
Box::new(f)
}
fn new_fn(
params: Self::Params,
initial_value: &Self::Input,
) -> Result<BoxedFnMethod<Self>, Error>
where
Self: Sized + 'static,
{
let instance = Self::new(params, initial_value)?;
Ok(instance.into_fn())
}
}