1use crate::{Function, FunctionSet};
2use anyhow::anyhow;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::sync::Arc;
6use wd_tools::{PFErr, PFOk};
7
8pub trait FromValue: Sized {
9 fn from(val: Value) -> anyhow::Result<Self>;
10}
11impl<T> FromValue for T
85where
86 T: for<'a> Deserialize<'a>,
87{
88 fn from(val: Value) -> anyhow::Result<Self> {
89 let t: T = serde_json::from_value(val)?;
90 t.ok()
91 }
92}
93
94pub trait HostFunction<A, O>: Send + Sync {
95 fn call(&self, args: Vec<Value>) -> anyhow::Result<Value>;
96}
97pub struct FunctionImpl<A, O> {
98 inner: Box<dyn HostFunction<A, O>>,
99}
100
101impl<A, O> FunctionImpl<A, O> {
102 pub fn new<F: HostFunction<A, O> + Send + Sync + 'static>(f: F) -> Self {
103 let inner = Box::new(f);
104 Self { inner }
105 }
106}
107
108impl<A, O> Function for FunctionImpl<A, O>
109where
110 O: Serialize,
111{
112 fn call(&self, _fs: Arc<dyn FunctionSet>, args: Vec<Value>) -> anyhow::Result<Value> {
113 self.inner.call(args)
114 }
115}
116impl<O, F> HostFunction<(), O> for F
117where
118 O: Serialize,
119 F: Fn() -> anyhow::Result<O> + Send + Sync + 'static,
120{
121 fn call(&self, _args: Vec<Value>) -> anyhow::Result<Value> {
122 let out = self()?;
123 let val = serde_json::to_value(out)?;
124 Ok(val)
125 }
126}
127macro_rules! function_impl_template {
128 ($n:tt,$($t:tt),*) => {
129 impl<$($t,)* O,F> HostFunction<($($t,)*),O> for F
130where $($t:FromValue,)*
131 O:Serialize,F:Fn($($t,)*)->anyhow::Result<O> + Send + Sync + 'static
132{
133 fn call(&self, mut args: Vec<Value>) -> anyhow::Result<Value> {
134 if args.len() < $n {
135 return anyhow!("expecting {} parameters actually finds {} parameters",$n,args.len()).err()
136 }
137 let out = self($($t::from(args.remove(0))?,)*)?;
138 let val = serde_json::to_value(out)?;
139 Ok(val)
140 }
141}
142 };
143}
144function_impl_template!(1, A1);
145function_impl_template!(2, A1, A2);
146function_impl_template!(3, A1, A2, A3);
147function_impl_template!(4, A1, A2, A3, A4);
148function_impl_template!(5, A1, A2, A3, A4, A5);
149function_impl_template!(6, A1, A2, A3, A4, A5, A6);
150function_impl_template!(7, A1, A2, A3, A4, A5, A6, A7);
151function_impl_template!(8, A1, A2, A3, A4, A5, A6, A7, A8);
152function_impl_template!(9, A1, A2, A3, A4, A5, A6, A7, A8, A9);
153function_impl_template!(10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
154function_impl_template!(11, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
155function_impl_template!(12, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
156function_impl_template!(13, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
157function_impl_template!(14, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
158function_impl_template!(15, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
159function_impl_template!(16, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
160
161#[cfg(test)]
162mod test {
163 use crate::{Function, FunctionImpl, FunctionSet, HostFunction};
164 use serde::Serialize;
165 use serde_json::Value;
166 use std::sync::Arc;
167 #[derive(Debug)]
168 struct FSet;
169 impl FunctionSet for FSet {
170 fn get(&self, _name: &str) -> Option<Arc<dyn Function>> {
171 None
172 }
173 }
174
175 fn call<A, O: Serialize, F: HostFunction<A, O> + 'static>(f: F) {
176 let f = FunctionImpl { inner: Box::new(f) };
177 let b: Box<dyn Function> = Box::new(f);
178 let _ = b
179 .call(
180 Arc::new(FSet {}),
181 vec![Value::String("hello".into()), Value::String("world".into())],
182 )
183 .unwrap();
184 }
186
187 #[test]
189 fn test_fn() {
190 call(|a: String| {
191 println!("--->{}", a);
192 Ok("hello")
193 });
194 }
195}