macro_rules! msg {
($msg:expr, $($tokens:tt)+) => { ... };
(@internal
$msg:expr,
($($bvar:ident, $bty:ty, $bhandle:expr,)*),
($($tvar:ident, $tty:ty, $thandle:expr,)*),
($($avar:ident, $aty:ty, $ahandle:expr,)*),
ref $var:ident: $ty:ty => $handle:expr;
$($rest:tt)+
) => { ... };
(@internal
$msg:expr,
($($bvar:ident, $bty:ty, $bhandle:expr,)*),
($($tvar:ident, $tty:ty, $thandle:expr,)*),
($($avar:ident, $aty:ty, $ahandle:expr,)*),
$var:ident: $ty:ty => $handle:expr;
$($rest:tt)+
) => { ... };
(@internal
$msg:expr,
($($bvar:ident, $bty:ty, $bhandle:expr,)*),
($($tvar:ident, $tty:ty, $thandle:expr,)*),
($($avar:ident, $aty:ty, $ahandle:expr,)*),
$var:ident: $ty:ty =!> $handle:expr;
$($rest:tt)+
) => { ... };
(@internal
$msg:expr,
($($bvar:ident, $bty:ty, $bhandle:expr,)*),
($($tvar:ident, $tty:ty, $thandle:expr,)*),
($($avar:ident, $aty:ty, $ahandle:expr,)*),
_: _ => $handle:expr;
) => { ... };
(@internal
$msg:expr,
($($bvar:ident, $bty:ty, $bhandle:expr,)*),
($($tvar:ident, $tty:ty, $thandle:expr,)*),
($($avar:ident, $aty:ty, $ahandle:expr,)*),
$var:ident: _ => $handle:expr;
) => { ... };
}Expand description
Matches a Msg (as returned by BastionContext::recv
or BastionContext::try_recv) with different types.
Each case is defined as:
- an optional
refwhich will make the case only match if the message was broadcasted - a variable name for the message if it matched this case
- a colon
- a type that the message must be of to match this case (note that if the message was broadcasted, the actual type of the variable will be a reference to this type)
- an arrow (
=>) with an optional bang (!) between the equal and greater-than signs which will make the case only match if the message can be answered - code that will be executed if the case matches
If the message can be answered (when using =!> instead
of => as said above), an answer can be sent by passing
it to the answer! macro that will be generated for this
use.
A default case is required, which is defined in the same
way as any other case but with its type set as _ (note
that it doesn’t has the optional ref or =!>).
§Example
// The message that will be broadcasted...
const BCAST_MSG: &'static str = "A message containing data (broadcast).";
// The message that will be "told" to the child...
const TELL_MSG: &'static str = "A message containing data (tell).";
// The message that will be "asked" to the child...
const ASK_MSG: &'static str = "A message containing data (ask).";
Bastion::children(|children| {
children.with_exec(|ctx: BastionContext| {
async move {
loop {
msg! { ctx.recv().await?,
// We match broadcasted `&'static str`s...
ref msg: &'static str => {
// Note that `msg` will actually be a `&&'static str`.
assert_eq!(msg, &BCAST_MSG);
// Handle the message...
};
// We match `&'static str`s "told" to this child...
msg: &'static str => {
assert_eq!(msg, TELL_MSG);
// Handle the message...
};
// We match `&'static str`'s "asked" to this child...
msg: &'static str =!> {
assert_eq!(msg, ASK_MSG);
// Handle the message...
// ...and eventually answer to it...
answer!(ctx, "An answer to the message.");
};
// We are only broadcasting, "telling" and "asking" a
// `&'static str` in this example, so we know that this won't
// happen...
_: _ => ();
}
}
}
})
}).expect("Couldn't start the children group.");