1 //! Wrapper structs for the generic `Function` and `Method` traits
2 use std::sync::Arc;
3 
4 use crate::host::from_polar::FromPolarList;
5 use crate::host::to_polar::{PolarIterator, ToPolar, ToPolarResult};
6 
7 use super::class::{Class, Instance};
8 use super::method::{Function, Method};
9 use super::{Host, PolarValue};
10 
join<A, B>(left: crate::Result<A>, right: crate::Result<B>) -> crate::Result<(A, B)>11 fn join<A, B>(left: crate::Result<A>, right: crate::Result<B>) -> crate::Result<(A, B)> {
12     left.and_then(|l| right.map(|r| (l, r)))
13 }
14 
15 type TypeErasedFunction<R> = Arc<dyn Fn(Vec<PolarValue>) -> crate::Result<R> + Send + Sync>;
16 type TypeErasedMethod<R> =
17     Arc<dyn Fn(&Instance, Vec<PolarValue>, &mut Host) -> crate::Result<R> + Send + Sync>;
18 
19 #[derive(Clone)]
20 pub struct RegisterHook(Arc<dyn Fn(&mut crate::Oso) -> crate::Result<()> + Send + Sync + 'static>);
21 
22 impl RegisterHook {
new<F>(f: F) -> Self where F: Fn(&mut crate::Oso) -> crate::Result<()> + Send + Sync + 'static,23     pub fn new<F>(f: F) -> Self
24     where
25         F: Fn(&mut crate::Oso) -> crate::Result<()> + Send + Sync + 'static,
26     {
27         RegisterHook(Arc::new(f))
28     }
29 
call(&self, oso: &mut crate::Oso) -> crate::Result<()>30     pub fn call(&self, oso: &mut crate::Oso) -> crate::Result<()> {
31         (self.0)(oso)
32     }
33 }
34 
35 #[derive(Clone)]
36 pub struct Constructor(TypeErasedFunction<Instance>);
37 
38 impl Constructor {
new<Args, F>(f: F) -> Self where Args: FromPolarList, F: Function<Args>, F::Result: Send + Sync + 'static,39     pub fn new<Args, F>(f: F) -> Self
40     where
41         Args: FromPolarList,
42         F: Function<Args>,
43         F::Result: Send + Sync + 'static,
44     {
45         Constructor(Arc::new(move |args: Vec<PolarValue>| {
46             Args::from_polar_list(&args).map(|args| Instance::new(f.invoke(args)))
47         }))
48     }
49 
invoke(&self, args: Vec<PolarValue>) -> crate::Result<Instance>50     pub fn invoke(&self, args: Vec<PolarValue>) -> crate::Result<Instance> {
51         self.0(args)
52     }
53 }
54 
55 #[derive(Clone)]
56 pub struct AttributeGetter(
57     Arc<dyn Fn(&Instance, &mut Host) -> crate::Result<PolarValue> + Send + Sync>,
58 );
59 
60 impl AttributeGetter {
new<T, F, R>(f: F) -> Self where T: 'static, F: Fn(&T) -> R + Send + Sync + 'static, R: ToPolarResult,61     pub fn new<T, F, R>(f: F) -> Self
62     where
63         T: 'static,
64         F: Fn(&T) -> R + Send + Sync + 'static,
65         R: ToPolarResult,
66     {
67         Self(Arc::new(move |receiver, host: &mut Host| {
68             let receiver = receiver
69                 .downcast(Some(&host))
70                 .map_err(|e| e.invariant().into());
71             receiver.map(&f).and_then(|v| v.to_polar_result())
72         }))
73     }
74 
invoke(&self, receiver: &Instance, host: &mut Host) -> crate::Result<PolarValue>75     pub fn invoke(&self, receiver: &Instance, host: &mut Host) -> crate::Result<PolarValue> {
76         self.0(receiver, host)
77     }
78 }
79 
80 #[derive(Clone)]
81 pub struct InstanceMethod(TypeErasedMethod<PolarValue>);
82 
83 impl InstanceMethod {
new<T, F, Args>(f: F) -> Self where Args: FromPolarList, F: Method<T, Args>, F::Result: ToPolarResult, T: 'static,84     pub fn new<T, F, Args>(f: F) -> Self
85     where
86         Args: FromPolarList,
87         F: Method<T, Args>,
88         F::Result: ToPolarResult,
89         T: 'static,
90     {
91         Self(Arc::new(
92             move |receiver: &Instance, args: Vec<PolarValue>, host: &mut Host| {
93                 let receiver = receiver
94                     .downcast(Some(&host))
95                     .map_err(|e| e.invariant().into());
96 
97                 let args = Args::from_polar_list(&args);
98 
99                 join(receiver, args)
100                     .and_then(|(receiver, args)| f.invoke(receiver, args).to_polar_result())
101             },
102         ))
103     }
104 
new_iterator<T, F, Args, I>(f: F) -> Self where Args: FromPolarList, F: Method<T, Args>, F::Result: IntoIterator<Item = I>, <<F as Method<T, Args>>::Result as IntoIterator>::IntoIter: Iterator<Item = I> + Clone + Send + Sync + 'static, I: ToPolarResult, T: 'static,105     pub fn new_iterator<T, F, Args, I>(f: F) -> Self
106     where
107         Args: FromPolarList,
108         F: Method<T, Args>,
109         F::Result: IntoIterator<Item = I>,
110         <<F as Method<T, Args>>::Result as IntoIterator>::IntoIter:
111             Iterator<Item = I> + Clone + Send + Sync + 'static,
112         I: ToPolarResult,
113         T: 'static,
114     {
115         Self(Arc::new(
116             move |receiver: &Instance, args: Vec<PolarValue>, host: &mut Host| {
117                 let receiver = receiver
118                     .downcast(Some(&host))
119                     .map_err(|e| e.invariant().into());
120 
121                 let args = Args::from_polar_list(&args);
122 
123                 join(receiver, args)
124                     .map(|(receiver, args)| {
125                         PolarIterator::new(f.invoke(receiver, args).into_iter())
126                     })
127                     .map(|results| results.to_polar())
128             },
129         ))
130     }
131 
invoke( &self, receiver: &Instance, args: Vec<PolarValue>, host: &mut Host, ) -> crate::Result<PolarValue>132     pub fn invoke(
133         &self,
134         receiver: &Instance,
135         args: Vec<PolarValue>,
136         host: &mut Host,
137     ) -> crate::Result<PolarValue> {
138         self.0(receiver, args, host)
139     }
140 
from_class_method(name: String) -> Self141     pub fn from_class_method(name: String) -> Self {
142         Self(Arc::new(
143             move |receiver: &Instance, args: Vec<PolarValue>, host: &mut Host| {
144                 receiver
145                     .downcast::<Class>(Some(&host))
146                     .map_err(|e| e.invariant().into())
147                     .and_then(|class| {
148                         tracing::trace!(class = %class.name, method=%name, "class_method");
149                         class.call(&name, args)
150                     })
151             },
152         ))
153     }
154 }
155 
156 #[derive(Clone)]
157 pub struct ClassMethod(TypeErasedFunction<PolarValue>);
158 
159 impl ClassMethod {
new<F, Args>(f: F) -> Self where Args: FromPolarList, F: Function<Args>, F::Result: ToPolarResult,160     pub fn new<F, Args>(f: F) -> Self
161     where
162         Args: FromPolarList,
163         F: Function<Args>,
164         F::Result: ToPolarResult,
165     {
166         Self(Arc::new(move |args: Vec<PolarValue>| {
167             Args::from_polar_list(&args).and_then(|args| f.invoke(args).to_polar_result())
168         }))
169     }
170 
invoke(&self, args: Vec<PolarValue>) -> crate::Result<PolarValue>171     pub fn invoke(&self, args: Vec<PolarValue>) -> crate::Result<PolarValue> {
172         self.0(args)
173     }
174 }
175