mod handler;
pub mod di;
pub mod prelude;
pub use handler::*;
#[macro_export]
macro_rules! case {
($($variant:ident)::+) => {
$crate::filter(|x| matches!(x, $($variant)::+))
};
($($variant:ident)::+ ($param:ident)) => {
$crate::filter_map(|x| match x {
$($variant)::+($param) => Some($param),
_ => None,
})
};
($($variant:ident)::+ ($($param:ident),+ $(,)?)) => {
$crate::filter_map(|x| match x {
$($variant)::+($($param),+) => Some(($($param),+ ,)),
_ => None,
})
};
($($variant:ident)::+ {$param:ident}) => {
$crate::filter_map(|x| match x {
$($variant)::+{$param} => Some($param),
_ => None,
})
};
($($variant:ident)::+ {$($param:ident),+ $(,)?}) => {
$crate::filter_map(|x| match x {
$($variant)::+ { $($param),+ } => Some(($($param),+ ,)),
_ => None,
})
};
}
#[cfg(test)]
mod tests {
use std::ops::ControlFlow;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum State {
A,
B(i32),
C(i32, &'static str),
D { foo: i32 },
E { foo: i32, bar: &'static str },
Other,
}
#[tokio::test]
async fn handler_empty_variant() {
let input = State::A;
let h: crate::Handler<_, _> = case![State::A].endpoint(|| async move { 123 });
assert_eq!(h.dispatch(crate::deps![input]).await, ControlFlow::Break(123));
assert!(matches!(h.dispatch(crate::deps![State::Other]).await, ControlFlow::Continue(_)));
}
#[tokio::test]
async fn handler_single_fn_variant() {
let input = State::B(42);
let h: crate::Handler<_, _> = case![State::B(x)].endpoint(|x: i32| async move {
assert_eq!(x, 42);
123
});
assert_eq!(h.dispatch(crate::deps![input]).await, ControlFlow::Break(123));
assert!(matches!(h.dispatch(crate::deps![State::Other]).await, ControlFlow::Continue(_)));
}
#[tokio::test]
async fn handler_single_fn_variant_trailing_comma() {
let input = State::B(42);
let h: crate::Handler<_, _> = case![State::B(x,)].endpoint(|(x,): (i32,)| async move {
assert_eq!(x, 42);
123
});
assert_eq!(h.dispatch(crate::deps![input]).await, ControlFlow::Break(123));
assert!(matches!(h.dispatch(crate::deps![State::Other]).await, ControlFlow::Continue(_)));
}
#[tokio::test]
async fn handler_fn_variant() {
let input = State::C(42, "abc");
let h: crate::Handler<_, _> =
case![State::C(x, y)].endpoint(|(x, str): (i32, &'static str)| async move {
assert_eq!(x, 42);
assert_eq!(str, "abc");
123
});
assert_eq!(h.dispatch(crate::deps![input]).await, ControlFlow::Break(123));
assert!(matches!(h.dispatch(crate::deps![State::Other]).await, ControlFlow::Continue(_)));
}
#[tokio::test]
async fn handler_single_struct_variant() {
let input = State::D { foo: 42 };
let h: crate::Handler<_, _> = case![State::D { foo }].endpoint(|x: i32| async move {
assert_eq!(x, 42);
123
});
assert_eq!(h.dispatch(crate::deps![input]).await, ControlFlow::Break(123));
assert!(matches!(h.dispatch(crate::deps![State::Other]).await, ControlFlow::Continue(_)));
}
#[tokio::test]
async fn handler_single_struct_variant_trailing_comma() {
let input = State::D { foo: 42 };
#[rustfmt::skip] let h: crate::Handler<_, _> = case![State::D { foo, }].endpoint(|(x,): (i32,)| async move {
assert_eq!(x, 42);
123
});
assert_eq!(h.dispatch(crate::deps![input]).await, ControlFlow::Break(123));
assert!(matches!(h.dispatch(crate::deps![State::Other]).await, ControlFlow::Continue(_)));
}
#[tokio::test]
async fn handler_struct_variant() {
let input = State::E { foo: 42, bar: "abc" };
let h: crate::Handler<_, _> =
case![State::E { foo, bar }].endpoint(|(x, str): (i32, &'static str)| async move {
assert_eq!(x, 42);
assert_eq!(str, "abc");
123
});
assert_eq!(h.dispatch(crate::deps![input]).await, ControlFlow::Break(123));
assert!(matches!(h.dispatch(crate::deps![State::Other]).await, ControlFlow::Continue(_)));
}
}