plux_rs/function/
function.rs

1use std::fmt::{Debug, Display};
2
3use crate::variable::Variable;
4
5use super::Arg;
6
7pub trait Function: Send + Sync {
8    type Output: Send + Sync;
9
10    fn name(&self) -> String;
11    fn inputs(&self) -> Vec<Arg>;
12    fn output(&self) -> Option<Arg>;
13    fn call(&self, args: &[Variable]) -> Self::Output;
14}
15
16impl<O: Send + Sync> PartialEq for dyn Function<Output = O> {
17    fn eq(&self, other: &Self) -> bool {
18        self.name() == other.name()
19            && self.inputs() == other.inputs()
20            && self.output() == other.output()
21    }
22}
23
24impl<O: Send + Sync> Eq for dyn Function<Output = O> {}
25
26impl<O: Send + Sync> Display for dyn Function<Output = O> {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        //TODO: Внедрить описание функций в August
29        // // Комментарий в виде описания функции
30        // write!(f, "# {}\n", self.description);
31
32        // Функция
33        write!(
34            f,
35            "{}({}) -> {}",
36            self.name(),
37            self.inputs()
38                .iter()
39                .map(|x| format!("{x}"))
40                .collect::<Vec<_>>()
41                .join(", "),
42            match self.output() {
43                Some(arg) => format!("{}({})", arg.name, arg.ty),
44                None => "void".to_string(),
45            }
46        )
47    }
48}
49
50impl<O: Send + Sync> Debug for dyn Function<Output = O> {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        Display::fmt(self, f)
53    }
54}
55
56pub type FunctionOutput = Result<Option<Variable>, Box<dyn std::error::Error + Send + Sync>>;
57
58pub struct DynamicFunction {
59    name: String,
60    inputs: Vec<Arg>,
61    output: Option<Arg>,
62    ptr: Box<dyn Fn(&[Variable]) -> FunctionOutput + Send + Sync>,
63}
64
65impl DynamicFunction {
66    pub fn new<S, F>(name: S, inputs: Vec<Arg>, output: Option<Arg>, ptr: F) -> Self
67    where
68        S: Into<String>,
69        F: Fn(&[Variable]) -> FunctionOutput + Send + Sync + 'static,
70    {
71        Self {
72            name: name.into(),
73            inputs,
74            output,
75            ptr: Box::new(ptr),
76        }
77    }
78}
79
80impl Function for DynamicFunction {
81    type Output = FunctionOutput;
82
83    fn name(&self) -> String {
84        self.name.clone()
85    }
86
87    fn inputs(&self) -> Vec<Arg> {
88        self.inputs.clone()
89    }
90
91    fn output(&self) -> Option<Arg> {
92        self.output.clone()
93    }
94
95    fn call(&self, args: &[Variable]) -> Self::Output {
96        (self.ptr)(args)
97    }
98}
99
100#[test]
101fn function_call() {
102    use crate::variable::VariableType;
103
104    // Создание функции
105    let func = DynamicFunction::new(
106        "add",
107        vec![
108            Arg::new("a", VariableType::I32),
109            Arg::new("b", VariableType::I32),
110        ],
111        Some(Arg::new("c", VariableType::I32)),
112        |args| -> FunctionOutput {
113            let a = args[0].parse_ref::<i32>();
114            let b = args[1].parse_ref::<i32>();
115
116            let c = a + b;
117
118            println!("{} + {} = {}", a, b, c);
119
120            Ok(Some(c.into()))
121        },
122    );
123
124    // Запуск функции
125    let c = func.call(&[1.into(), 2.into()]);
126
127    assert!(c.is_ok());
128    assert_eq!(c.unwrap(), Some(3.into()));
129}
130
131#[test]
132fn parallel_call() {
133    use crate::variable::VariableType;
134    use std::{sync::Arc, thread, time::Duration};
135
136    // Создание функции
137    let func = DynamicFunction::new(
138        "log",
139        vec![Arg::new("n", VariableType::I32)],
140        None,
141        |args| -> FunctionOutput {
142            let n = args[0].parse_ref::<i32>();
143
144            println!("Step {n}");
145
146            Ok(None)
147        },
148    );
149
150    // Вызов функции в нескольких потоках
151    let func = Arc::new(func);
152
153    let mut handles = vec![];
154    for i in 0..10 {
155        let func = func.clone();
156        let args: Arc<[Variable]> = Arc::new([i.into()]);
157
158        handles.push(thread::spawn(move || {
159            thread::sleep(Duration::from_secs(1));
160
161            let result = func.call(&args.as_ref());
162
163            assert!(result.is_ok());
164            assert_eq!(result.unwrap(), None);
165        }));
166    }
167
168    for handle in handles {
169        handle.join().unwrap();
170    }
171}