mod input;
mod output;
use crate::instant::Instant;
use std::rc::Rc;
pub use input::*;
pub use output::*;
pub unsafe trait Action {
type Text: ?Sized;
type State;
type Heap;
type Value;
fn exec(
&self,
input: Input<&Instant<&Self::Text>, &mut Self::State, &mut Self::Heap>,
) -> Option<Output<Self::Value>>;
}
unsafe impl<T: Action + ?Sized> Action for &T {
type Text = T::Text;
type State = T::State;
type Heap = T::Heap;
type Value = T::Value;
#[inline]
fn exec(
&self,
input: Input<&Instant<&Self::Text>, &mut Self::State, &mut Self::Heap>,
) -> Option<Output<Self::Value>> {
(**self).exec(input)
}
}
unsafe impl<T: Action + ?Sized> Action for Box<T> {
type Text = T::Text;
type State = T::State;
type Heap = T::Heap;
type Value = T::Value;
#[inline]
fn exec(
&self,
input: Input<&Instant<&Self::Text>, &mut Self::State, &mut Self::Heap>,
) -> Option<Output<Self::Value>> {
self.as_ref().exec(input)
}
}
unsafe impl<T: Action + ?Sized> Action for Rc<T> {
type Text = T::Text;
type State = T::State;
type Heap = T::Heap;
type Value = T::Value;
#[inline]
fn exec(
&self,
input: Input<&Instant<&Self::Text>, &mut Self::State, &mut Self::Heap>,
) -> Option<Output<Self::Value>> {
self.as_ref().exec(input)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
combinator::{bytes, take},
instant::Instant,
};
fn assert_str_action(t: impl Action<Text = str, State = (), Heap = (), Value = ()>) {
assert!(t
.exec(Input {
instant: &Instant::new("123"),
state: &mut (),
heap: &mut ()
})
.is_some());
}
fn assert_bytes_action(t: impl Action<Text = [u8], State = (), Heap = (), Value = ()>) {
assert!(t
.exec(Input {
instant: &Instant::new(b"123"),
state: &mut (),
heap: &mut ()
})
.is_some());
}
#[test]
fn action_ref() {
assert_str_action(&take(1));
assert_bytes_action(&bytes::take(1));
}
#[test]
fn action_dyn_ref() {
assert_str_action(&take(1) as &dyn Action<Text = str, State = (), Heap = (), Value = ()>);
assert_bytes_action(
&bytes::take(1) as &dyn Action<Text = [u8], State = (), Heap = (), Value = ()>
);
}
#[test]
fn boxed_action() {
assert_str_action(Box::new(take(1)));
assert_bytes_action(Box::new(bytes::take(1)));
}
#[test]
fn boxed_dyn_action() {
assert_str_action(
Box::new(take(1)) as Box<dyn Action<Text = str, State = (), Heap = (), Value = ()>>
);
assert_bytes_action(
Box::new(bytes::take(1)) as Box<dyn Action<Text = [u8], State = (), Heap = (), Value = ()>>
);
}
#[test]
fn rc_action() {
assert_str_action(Rc::new(take(1)));
assert_bytes_action(Rc::new(bytes::take(1)));
}
#[test]
fn rc_dyn_action() {
assert_str_action(
Rc::new(take(1)) as Rc<dyn Action<Text = str, State = (), Heap = (), Value = ()>>
);
assert_bytes_action(
Rc::new(bytes::take(1)) as Rc<dyn Action<Text = [u8], State = (), Heap = (), Value = ()>>
);
}
}