blueprint_engine_core/value/
functions.rs

1use std::collections::HashMap;
2use std::fmt;
3use std::future::Future;
4use std::pin::Pin;
5use std::sync::Arc;
6
7use super::Value;
8use crate::error::Result;
9
10pub type NativeFuture = Pin<Box<dyn Future<Output = Result<Value>> + Send>>;
11pub type NativeFn = Arc<dyn Fn(Vec<Value>, HashMap<String, Value>) -> NativeFuture + Send + Sync>;
12
13#[derive(Debug, Clone)]
14pub struct Parameter {
15    pub name: String,
16    pub default: Option<Value>,
17    pub kind: ParameterKind,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq)]
21pub enum ParameterKind {
22    Positional,
23    Args,
24    Kwargs,
25}
26
27pub struct UserFunction {
28    pub name: String,
29    pub params: Vec<Parameter>,
30    pub body: Box<dyn std::any::Any + Send + Sync>,
31    pub closure: Option<Arc<dyn std::any::Any + Send + Sync>>,
32}
33
34impl fmt::Debug for UserFunction {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        f.debug_struct("UserFunction")
37            .field("name", &self.name)
38            .field("params", &self.params)
39            .finish()
40    }
41}
42
43pub struct LambdaFunction {
44    pub params: Vec<Parameter>,
45    pub body: Box<dyn std::any::Any + Send + Sync>,
46    pub closure: Option<Arc<dyn std::any::Any + Send + Sync>>,
47}
48
49impl fmt::Debug for LambdaFunction {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        f.debug_struct("LambdaFunction")
52            .field("params", &self.params)
53            .finish()
54    }
55}
56
57pub struct NativeFunction {
58    pub name: String,
59    pub func: NativeFn,
60}
61
62impl fmt::Debug for NativeFunction {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        f.debug_struct("NativeFunction")
65            .field("name", &self.name)
66            .finish()
67    }
68}
69
70impl NativeFunction {
71    pub fn new<F, Fut>(name: impl Into<String>, f: F) -> Self
72    where
73        F: Fn(Vec<Value>, HashMap<String, Value>) -> Fut + Send + Sync + 'static,
74        Fut: Future<Output = Result<Value>> + Send + 'static,
75    {
76        NativeFunction {
77            name: name.into(),
78            func: Arc::new(move |args, kwargs| Box::pin(f(args, kwargs))),
79        }
80    }
81
82    pub fn new_with_state<F>(name: impl Into<String>, f: F) -> Self
83    where
84        F: Fn(Vec<Value>, HashMap<String, Value>) -> NativeFuture + Send + Sync + 'static,
85    {
86        NativeFunction {
87            name: name.into(),
88            func: Arc::new(f),
89        }
90    }
91
92    pub async fn call(&self, args: Vec<Value>, kwargs: HashMap<String, Value>) -> Result<Value> {
93        (self.func)(args, kwargs).await
94    }
95}