1use crate::error::HandlerError;
8use crate::value::Value;
9use std::any::Any;
10use std::future::Future;
11use std::pin::Pin;
12use std::rc::Rc;
13
14pub type HandlerReturn = Result<StepOutput, HandlerError>;
17
18pub enum StepOutput {
23 State(Rc<dyn Any>),
24 Compared(Option<Value>),
25}
26
27impl StepOutput {
28 pub fn compared(&self) -> Option<&Value> {
30 match self {
31 StepOutput::Compared(v) => v.as_ref(),
32 StepOutput::State(_) => None,
33 }
34 }
35}
36
37pub enum StepReturn {
39 Ready(HandlerReturn),
40 Pending(Pin<Box<dyn Future<Output = HandlerReturn>>>),
41}
42
43fn value_state(state: &Rc<dyn Any>) -> Value {
45 state
46 .downcast_ref::<Value>()
47 .cloned()
48 .unwrap_or(Value::Null)
49}
50
51type HandlerFn = dyn Fn(Rc<dyn Any>, Vec<Value>) -> StepReturn;
54
55#[derive(Clone)]
57pub struct Handler {
58 f: Rc<HandlerFn>,
59}
60
61impl Handler {
62 pub fn noop() -> Handler {
64 Handler {
65 f: Rc::new(|_state, _args| StepReturn::Ready(Ok(StepOutput::Compared(None)))),
66 }
67 }
68
69 pub fn new(f: impl Fn(Rc<dyn Any>, Vec<Value>) -> HandlerReturn + 'static) -> Handler {
73 Handler {
74 f: Rc::new(move |state, args| StepReturn::Ready(f(state, args))),
75 }
76 }
77
78 pub fn sync0(f: impl Fn(Value) -> Result<Option<Value>, HandlerError> + 'static) -> Handler {
83 Handler::new(move |state, args| {
84 if !args.is_empty() {
85 return Err(HandlerError::new("no handler with 0 parameter(s)"));
86 }
87 Ok(StepOutput::Compared(f(value_state(&state))?))
88 })
89 }
90
91 pub fn sync1(
93 f: impl Fn(Value, Value) -> Result<Option<Value>, HandlerError> + 'static,
94 ) -> Handler {
95 Handler::new(move |state, args| {
96 if args.len() != 1 {
97 return Err(HandlerError::new("no handler with 1 parameter(s)"));
98 }
99 Ok(StepOutput::Compared(f(value_state(&state), args[0].clone())?))
100 })
101 }
102
103 pub fn sync2(
105 f: impl Fn(Value, Value, Value) -> Result<Option<Value>, HandlerError> + 'static,
106 ) -> Handler {
107 Handler::new(move |state, args| {
108 if args.len() != 2 {
109 return Err(HandlerError::new("no handler with 2 parameter(s)"));
110 }
111 Ok(StepOutput::Compared(f(value_state(&state), args[0].clone(), args[1].clone())?))
112 })
113 }
114
115 pub fn state1(f: impl Fn(Value, Value) -> Result<Value, HandlerError> + 'static) -> Handler {
118 Handler::new(move |state, args| {
119 if args.len() != 1 {
120 return Err(HandlerError::new("no handler with 1 parameter(s)"));
121 }
122 Ok(StepOutput::State(Rc::new(f(value_state(&state), args[0].clone())?)))
123 })
124 }
125
126 pub fn async0(
128 f: impl Fn(Value) -> Pin<Box<dyn Future<Output = HandlerReturn>>> + 'static,
129 ) -> Handler {
130 Handler {
131 f: Rc::new(move |state, args| {
132 if !args.is_empty() {
133 return StepReturn::Ready(Err(HandlerError::new(
134 "no handler with 0 parameter(s)",
135 )));
136 }
137 StepReturn::Pending(f(value_state(&state)))
138 }),
139 }
140 }
141
142 pub fn sync_var(
144 f: impl Fn(Value, Vec<Value>) -> Result<Option<Value>, HandlerError> + 'static,
145 ) -> Handler {
146 Handler::new(move |state, args| Ok(StepOutput::Compared(f(value_state(&state), args)?)))
147 }
148
149 pub fn async_var(
151 f: impl Fn(Value, Vec<Value>) -> Pin<Box<dyn Future<Output = HandlerReturn>>> + 'static,
152 ) -> Handler {
153 Handler {
154 f: Rc::new(move |state, args| StepReturn::Pending(f(value_state(&state), args))),
155 }
156 }
157
158 pub(crate) fn call(&self, state: Rc<dyn Any>, args: Vec<Value>) -> StepReturn {
160 (self.f)(state, args)
161 }
162}