1use crate::Ref;
2use core::fmt::{Display, Error, Formatter};
3
4use alloc::string::ToString;
5
6#[derive(Clone)]
9pub struct Function<I, O, C> {
10 function_ptr: Ref<dyn Fn(&mut I) -> O>,
12 context: C,
14}
15
16impl<I, O, C> Function<I, O, C> {
19 pub fn new(function_ptr: impl 'static + Fn(&mut I) -> O, context: C) -> Self {
23 Self {
24 function_ptr: Ref::new(function_ptr),
25 context,
26 }
27 }
28
29 pub fn get_context(&self) -> &C {
31 &self.context
32 }
33
34 pub fn call(&self, input: &mut I) -> O {
36 (self.function_ptr)(input)
37 }
38}
39
40impl<I, O, C> Display for Function<I, O, C> {
41 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
42 let ptr = Ref::into_raw(self.function_ptr.clone()) as *const u8;
43 write!(f, "<fn at {}>", format!("{:?}", ptr)[..8].to_string())?;
44 unsafe {
45 Ref::from_raw(ptr);
46 }
47 Ok(())
48 }
49}
50
51impl<I, O, C> PartialEq for Function<I, O, C> {
56 fn eq(&self, rhs: &Self) -> bool {
57 format!("{}", self) == format!("{}", rhs)
58 }
59}
60
61impl<I, O, C: PartialOrd> PartialOrd for Function<I, O, C> {
65 fn partial_cmp(&self, rhs: &Self) -> Option<core::cmp::Ordering> {
66 self.context.partial_cmp(&rhs.context)
67 }
68}
69
70impl<I, O, C> Default for Function<I, O, C>
71where
72 I: Default,
73 O: Default,
74 C: Default,
75{
76 fn default() -> Self {
77 Self::new(|_: &mut I| Default::default(), Default::default())
78 }
79}