Skip to content

Commit

Permalink
Added a "message" macro to match a boxed Message against types
Browse files Browse the repository at this point in the history
  • Loading branch information
r3v2d0g committed Oct 24, 2019
1 parent d449799 commit e09764e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 7 deletions.
16 changes: 11 additions & 5 deletions bastion/examples/send_recv.rs
Expand Up @@ -10,19 +10,25 @@ fn main() {
let try_recv = ctx.try_recv().await;
println!("try_recv.is_some() == {}", try_recv.is_some()); // false

ctx.send_msg(ctx.as_ref(), Box::new("Hello World!")).ok();
ctx.current().send_msg(Box::new("Hello World!")).ok();

// This will return Ok(Box("Hello World!")).
let recv = ctx.recv().await;
println!("recv.is_ok() == {}", recv.is_ok()); // true
message! { ctx.recv().await?,
msg: &'static str => {
println!(r#"msg == "Hello World!" => {}"#, msg == &"Hello World!"); // true
},
// This won't happen because we know that this
// example only sends a `&'static str`...
_ => unreachable!(),
}

// Panicking will restart the children group.
panic!("Oh no!");
}
.into()
},
1,
).expect("Couldn't start a new children group.");
)
.expect("Couldn't start a new children group.");

Bastion::start();
Bastion::block_until_stopped();
Expand Down
5 changes: 3 additions & 2 deletions bastion/src/lib.rs
Expand Up @@ -3,16 +3,17 @@ pub use self::bastion::Bastion;
mod bastion;
mod broadcast;
mod context;
mod macros;
mod proc;
mod system;

pub mod children;
pub mod supervisor;

pub mod prelude {
pub use crate::Bastion;

pub use crate::children::{ChildRef, ChildrenRef, Closure, Fut, Message, Shell};
pub use crate::context::BastionContext;
pub use crate::message;
pub use crate::supervisor::{SupervisionStrategy, Supervisor, SupervisorRef};
pub use crate::Bastion;
}
65 changes: 65 additions & 0 deletions bastion/src/macros.rs
@@ -0,0 +1,65 @@
#[macro_export]
/// Matches a boxed [`Message`] (`Box<dyn Message>` as returned
/// by [`BastionContext::recv`] or [`BastionContext::try_recv`])
/// with different types.
///
/// Each case is defined as a variable name followed by a colon,
/// a type, and arrow and the code that will be executed if the
/// message is of the specified type.
///
/// Only a default case is required, which is defined in the
/// same way a `match` would define one (`_ => { ... }`).
///
/// # Example
///
/// ```
/// # use bastion::prelude::*;
/// #
/// # fn main() {
/// # Bastion::init();
/// // The message that will be sent...
/// let msg = "A message containing data.";
///
/// Bastion::children(|ctx: BastionContext|
/// async move {
/// let msg = ctx.recv().await?;
/// message! { msg,
/// msg: &'static str => {
/// assert_eq!(msg, &"A message containing data.");
/// },
/// // We are only sending a `&'static str` in this example,
/// // so we know that this won't happen...
/// _ => unreachable!(),
/// }
///
/// Ok(())
/// }.into(),
/// 1,
/// ).expect("Couldn't start the children group.");
/// #
/// # Bastion::start();
/// # Bastion::broadcast(Box::new(msg)).unwrap();
/// # Bastion::stop();
/// # Bastion::block_until_stopped();
/// # }
/// ```
///
/// [`Message`]: children/trait.Message.html
/// [`BastionContext::recv`]: struct.BastionContext.html#method.recv
/// [`BastionContext::try_recv`]: struct.BastionContext.html#method.try_recv
macro_rules! message {
($msg:expr,
$($var:ident: $ty:ty => $handle:expr,)*
_ => $fallback:expr,
) => {
if false {}
$(
if let Some($var) = $msg.as_any().downcast_ref::<$ty>() {
$handle
}
)*
else {
$fallback
}
};
}

0 comments on commit e09764e

Please sign in to comment.