Skip to content

Instantly share code, notes, and snippets.

@alerdenisov
Created September 30, 2020 16:07
Show Gist options
  • Save alerdenisov/ac0ae1db1bd4af4a9ee4dbb93d5db3e6 to your computer and use it in GitHub Desktop.
Save alerdenisov/ac0ae1db1bd4af4a9ee4dbb93d5db3e6 to your computer and use it in GitHub Desktop.
/// main.rs
pub fn start_foo_protocol(params: foo::FooParams) -> foo::FooExecution {
execute(params, foo::run)
}
///////// foo.rs
pub enum FooMessages {
MessageOne,
MessageTwo,
}
pub enum FooErrors {
ErrorOne,
ErrorTwo,
}
/// Result of protocol execution
pub struct FooResult;
/// Shorthand for protocol types definition
pub type FooProtocol = Protocol<FooMessages, FooResult, FooErrors>;
/// Shorthand for protocol execution definition
pub type FooExecution = ProtocolExecution<FooMessages, FooResult, FooErrors>;
/////// protocol.rs
/// Wrapped execution message
#[derive(Debug, Display, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "event", content = "body")]
pub enum Protocol<TM, TR, TE> {
#[display(fmt = "Packet {} ({} -> {})", data, sender, target)]
/// Communication message
Packet {
/// Sender of message
sender: u16,
/// Target recipient of message
target: u16,
/// Message data
data: TM,
},
#[display(fmt = "Complete")]
/// Protocol result message
Complete(TR),
#[display(fmt = "Quit")]
/// Exit message
Quit,
#[display(fmt = "Error: {:?}", _0)]
/// Error message
Error(TE),
#[display(fmt = "Log: {}", _0)]
/// Verbose logging message
Log(String),
}
/// Generic type to hold execution IO
pub struct ProtocolExecution<TM, TR, TE> {
/// Atomically referenced pointer to asynchronous message bus input
pub input: Sender<Protocol<TM, TR, TE>>,
/// Atomically referenced pointer to asynchronous message bus output
pub output: Receiver<Protocol<TM, TR, TE>>,
}
/// Generic wrapper about protocol execution function to auto generation IO message buses
pub fn execute<F, TParams, TM, TR, TE>(params: TParams, func: F) -> ProtocolExecution<TM, TR, TE>
where
F: Fn(TParams, &Receiver<Protocol<TM, TR, TE>>, &Sender<Protocol<TM, TR, TE>>) + Send + 'static,
TParams: Send + 'static,
TM: Send + 'static,
TR: Send + 'static,
TE: Send + 'static,
{
let (input_sender, input_receiver) = channel();
let (output_sender, output_receiver) = channel();
spawn(move || {
func(params, &input_receiver, &output_sender);
});
ProtocolExecution::new(input_sender, output_receiver)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment