use crate::Ref;
use core::fmt::{Display, Error, Formatter};
use alloc::string::ToString;
#[derive(Clone)]
pub struct Function<I, O, C> {
function_ptr: Ref<dyn Fn(&mut I) -> O>,
context: C,
}
impl<I, O, C> Function<I, O, C> {
pub fn new(function_ptr: impl 'static + Fn(&mut I) -> O, context: C) -> Self {
Self {
function_ptr: Ref::new(function_ptr),
context,
}
}
pub fn get_context(&self) -> &C {
&self.context
}
pub fn call(&self, input: &mut I) -> O {
(self.function_ptr)(input)
}
}
impl<I, O, C> Display for Function<I, O, C> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
let ptr = Ref::into_raw(self.function_ptr.clone()) as *const u8;
write!(f, "<fn at {}>", format!("{:?}", ptr)[..8].to_string())?;
unsafe {
Ref::from_raw(ptr);
}
Ok(())
}
}
impl<I, O, C> PartialEq for Function<I, O, C> {
fn eq(&self, rhs: &Self) -> bool {
format!("{}", self) == format!("{}", rhs)
}
}
impl<I, O, C: PartialOrd> PartialOrd for Function<I, O, C> {
fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
self.context.partial_cmp(&rhs.context)
}
}
impl<I, O, C> Default for Function<I, O, C>
where
I: Default,
O: Default,
C: Default,
{
fn default() -> Self {
Self::new(|_: &mut I| Default::default(), Default::default())
}
}