#![forbid(missing_docs)]
#![forbid(clippy::all)]
#![forbid(unsafe_code)]
pub type Essence<T, U> = fn(T) -> U;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Arrow<T, U = T> {
essence: Essence<T, U>,
symbiosis: Vec<Arrow<U, U>>,
}
impl<T> Arrow<T, ()> {
pub fn nop() -> Self {
Arrow::new(|_| ())
}
}
impl<T, U> Arrow<T, U> {
pub fn new(essence: fn(T) -> U) -> Self {
Arrow {
essence,
symbiosis: Vec::new(),
}
}
pub fn symbiotize(&mut self, other: Arrow<U, U>) -> usize {
self.symbiosis.push(other);
self.symbiosis.len() - 1
}
pub fn shoot(&self, input: T) -> U {
let mut result = (self.essence)(input);
for symbiote in &self.symbiosis {
result = symbiote.shoot(result);
}
result
}
pub fn shoot_reverse(&mut self, input: T) -> U {
let mut result = (self.essence)(input);
for symbiote in self.symbiosis.iter_mut().rev() {
result = symbiote.shoot_reverse(result);
}
result
}
pub fn clear(&mut self) {
self.symbiosis.clear();
}
pub fn remove(&mut self, idx: usize) {
self.symbiosis.remove(idx);
}
pub fn apply(&self, input: T) -> U {
(self.essence)(input)
}
}
impl<T, U> From<Essence<T, U>> for Arrow<T, U> {
fn from(essence: Essence<T, U>) -> Self {
Arrow::new(essence)
}
}
impl<T, U> Default for Arrow<T, U>
where
U: From<T>,
{
fn default() -> Self {
Arrow::new(U::from)
}
}