Make everything async
Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
parent
9ff1cf1bac
commit
f3f816acd9
5 changed files with 497 additions and 36 deletions
|
|
@ -13,5 +13,8 @@ categories = []
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
macro_rules_attribute = "0.2"
|
||||
smol-macros = "0.1"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
use std::any::Any;
|
||||
use std::any::TypeId;
|
||||
|
||||
pub use anyhow;
|
||||
|
||||
pub trait Message: Send + Any {
|
||||
type Reply: Send + Any;
|
||||
}
|
||||
|
|
@ -16,28 +18,44 @@ impl<M: Message> MessageIdentifier for M {
|
|||
const IDENT: BundleChain = BundleChain::of::<M>();
|
||||
}
|
||||
|
||||
pub struct InternalMessage(Box<dyn std::any::Any>);
|
||||
pub struct InternalMessage {
|
||||
value: Box<dyn std::any::Any>,
|
||||
name: &'static str,
|
||||
}
|
||||
|
||||
impl InternalMessage {
|
||||
pub fn new(message: impl Message) -> InternalMessage {
|
||||
InternalMessage(Box::new(message))
|
||||
pub fn new<M: Any>(message: M) -> InternalMessage {
|
||||
InternalMessage {
|
||||
value: Box::new(message),
|
||||
name: std::any::type_name::<M>(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_inner<M: Message>(self) -> Result<M, InternalMessage> {
|
||||
self.0.downcast().map(|v| *v).map_err(InternalMessage)
|
||||
pub fn into_inner<M: Any>(self) -> Result<M, InternalMessage> {
|
||||
self.value
|
||||
.downcast()
|
||||
.map(|v| *v)
|
||||
.map_err(|value| InternalMessage {
|
||||
value,
|
||||
name: self.name,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn type_name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Address<MB>
|
||||
where
|
||||
MB: MessageBundle,
|
||||
{
|
||||
fn send<M: Message>(&mut self, message: M);
|
||||
pub trait Address<MB> {
|
||||
fn send<M: Message>(&mut self, message: M) -> impl Future<Output = anyhow::Result<M::Reply>>;
|
||||
}
|
||||
|
||||
pub trait InternalMessageHandler {
|
||||
type HandledMessages: MessageBundle;
|
||||
fn handle_message(&mut self, msg: InternalMessage);
|
||||
fn handle_message(
|
||||
&mut self,
|
||||
msg: InternalMessage,
|
||||
) -> impl Future<Output = anyhow::Result<InternalMessage>>;
|
||||
}
|
||||
|
||||
impl<MB, IMH> Address<MB> for IMH
|
||||
|
|
@ -45,14 +63,26 @@ where
|
|||
MB: MessageBundle,
|
||||
IMH: InternalMessageHandler<HandledMessages = MB>,
|
||||
{
|
||||
fn send<M: Message>(&mut self, message: M) {
|
||||
fn send<M: Message>(&mut self, message: M) -> impl Future<Output = anyhow::Result<M::Reply>> {
|
||||
const {
|
||||
let true = <M as IsContainedInBundle<MB>>::IS_CONTAINED else {
|
||||
panic!("Message is not contained in MessageBundle",);
|
||||
};
|
||||
}
|
||||
|
||||
self.handle_message(InternalMessage(Box::new(message)));
|
||||
let message = self.handle_message(InternalMessage::new(message));
|
||||
|
||||
async {
|
||||
message.await.and_then(|msg| {
|
||||
msg.into_inner::<M::Reply>().map_err(|e| {
|
||||
anyhow::anyhow!(
|
||||
"Expected a {}, but got a {}",
|
||||
std::any::type_name::<M::Reply>(),
|
||||
e.type_name()
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,6 +203,9 @@ const fn remove_from_chain(prev: &'static BundleChain, to_remove: TypeId) -> Bun
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use macro_rules_attribute::apply;
|
||||
use smol_macros::test;
|
||||
|
||||
use super::*;
|
||||
|
||||
struct Foo;
|
||||
|
|
@ -218,18 +251,23 @@ mod tests {
|
|||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_sending_messages() {
|
||||
#[apply(test!)]
|
||||
async fn check_sending_messages() {
|
||||
struct Sender;
|
||||
|
||||
impl InternalMessageHandler for Sender {
|
||||
type HandledMessages = (Foo, Bar);
|
||||
|
||||
fn handle_message(&mut self, _msg: InternalMessage) {}
|
||||
async fn handle_message(
|
||||
&mut self,
|
||||
_msg: InternalMessage,
|
||||
) -> anyhow::Result<InternalMessage> {
|
||||
Err(anyhow::anyhow!("Not implemented!"))
|
||||
}
|
||||
}
|
||||
|
||||
let mut s = Sender;
|
||||
|
||||
s.send(Foo);
|
||||
s.send(Foo).await.unwrap_err();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue