Also map the reply

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2025-11-04 11:24:48 +01:00
parent 36966ff86d
commit 9fac3f08a1
2 changed files with 37 additions and 21 deletions

View file

@ -62,14 +62,13 @@ pub trait InternalMessageHandler {
) -> impl Future<Output = anyhow::Result<InternalMessage>>; ) -> impl Future<Output = anyhow::Result<InternalMessage>>;
} }
impl<MB, IMH> Address<MB> for IMH impl<IMH> Address<IMH::HandledMessages> for IMH
where where
MB: MessageBundle, IMH: InternalMessageHandler,
IMH: InternalMessageHandler<HandledMessages = MB>,
{ {
fn send<M: Message>(&mut self, message: M) -> impl Future<Output = anyhow::Result<M::Reply>> { fn send<M: Message>(&mut self, message: M) -> impl Future<Output = anyhow::Result<M::Reply>> {
const { const {
let true = <M as IsContainedInBundle<MB>>::IS_CONTAINED else { let true = <M as IsContainedInBundle<IMH::HandledMessages>>::IS_CONTAINED else {
panic!("Message is not contained in MessageBundle",); panic!("Message is not contained in MessageBundle",);
}; };
} }

View file

@ -1,7 +1,6 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use futures::FutureExt; use futures::FutureExt;
use tytix_core::Address;
use tytix_core::InternalMessage; use tytix_core::InternalMessage;
use tytix_core::InternalMessageHandler; use tytix_core::InternalMessageHandler;
use tytix_core::IsContainedInBundle; use tytix_core::IsContainedInBundle;
@ -9,13 +8,16 @@ use tytix_core::Message;
use tytix_core::MessageBundle; use tytix_core::MessageBundle;
use tytix_core::anyhow; use tytix_core::anyhow;
pub type ReplyOf<M> = <M as Message>::Reply;
pub trait AddressExt<MB> { pub trait AddressExt<MB> {
fn map_message<F, M, R, U>(self, f: F) -> MappedMessage<Self, F, M, R> fn map<M, R, F, U, RF, RU>(self, f: F, r: RF) -> MappedMessage<Self, M, F, U, RF, RU>
where where
F: Fn(M) -> U + 'static,
U: Future<Output = R>,
M: Message, M: Message,
R: Message + IsContainedInBundle<MB>, R: Message + IsContainedInBundle<MB>,
F: FnMut(M) -> U + 'static,
U: Future<Output = R>,
RF: FnMut(<R as Message>::Reply) -> RU + 'static,
Self: Sized; Self: Sized;
fn inspect<F, M, U>(self, f: F) -> Inspect<Self, F, U, M> fn inspect<F, M, U>(self, f: F) -> Inspect<Self, F, U, M>
@ -25,14 +27,13 @@ pub trait AddressExt<MB> {
Self: Sized; Self: Sized;
} }
impl<MB: MessageBundle, A: Address<MB>> AddressExt<MB> for A { impl<MB: MessageBundle, A: InternalMessageHandler<HandledMessages = MB>> AddressExt<MB> for A {
fn map_message<F, M, R, U>(self, f: F) -> MappedMessage<Self, F, M, R> fn map<M, R, F, U, RF, RU>(self, f: F, r: RF) -> MappedMessage<Self, M, F, U, RF, RU>
where where
MB: MessageBundle,
F: Fn(M) -> U + 'static,
U: Future<Output = R>,
M: Message, M: Message,
R: Message + IsContainedInBundle<MB>, R: Message + IsContainedInBundle<MB>,
F: FnMut(M) -> U + 'static,
RF: FnMut(<R as Message>::Reply) -> RU + 'static,
Self: Sized, Self: Sized,
{ {
const { const {
@ -44,6 +45,7 @@ impl<MB: MessageBundle, A: Address<MB>> AddressExt<MB> for A {
MappedMessage { MappedMessage {
address: self, address: self,
func: f, func: f,
reply: r,
_pd: PhantomData, _pd: PhantomData,
} }
} }
@ -91,10 +93,11 @@ where
} }
} }
pub struct MappedMessage<A, F, M, R> { pub struct MappedMessage<A, M, F, U, RF, RU> {
address: A, address: A,
func: F, func: F,
_pd: PhantomData<fn(M) -> R>, reply: RF,
_pd: PhantomData<fn(M) -> (U, RU)>,
} }
pub struct MappedHandledMessages<MB, M, R> { pub struct MappedHandledMessages<MB, M, R> {
@ -110,13 +113,15 @@ where
const IDS: tytix_core::BundleChain = MB::IDS.without::<R>().with::<M>(); const IDS: tytix_core::BundleChain = MB::IDS.without::<R>().with::<M>();
} }
impl<A, F, M, R, U> InternalMessageHandler for MappedMessage<A, F, M, R> impl<A, M, R, F, U, RF, RU> InternalMessageHandler for MappedMessage<A, M, F, U, RF, RU>
where where
A: InternalMessageHandler, A: InternalMessageHandler,
M: Message, M: Message,
R: Message + IsContainedInBundle<A::HandledMessages>, R: Message + IsContainedInBundle<A::HandledMessages>,
F: FnMut(M) -> U, F: FnMut(M) -> U,
U: Future<Output = R>, U: Future<Output = R>,
RF: FnMut(<R as Message>::Reply) -> RU,
RU: Future<Output = <M as Message>::Reply>,
{ {
type HandledMessages = MappedHandledMessages<A::HandledMessages, M, R>; type HandledMessages = MappedHandledMessages<A::HandledMessages, M, R>;
@ -135,7 +140,15 @@ where
async { async {
let msg = msg.await; let msg = msg.await;
self.address.handle_message(msg).await let msg_reply = self.address.handle_message(msg).await?;
let Ok(msg_reply) = msg_reply.into_inner() else {
return Err(anyhow::anyhow!("Internal Error: Received the wrong type"));
};
let msg_reply = (self.reply)(msg_reply).await;
Ok(InternalMessage::new(msg_reply))
} }
} }
} }
@ -146,6 +159,7 @@ mod tests {
use macro_rules_attribute::apply; use macro_rules_attribute::apply;
use smol_macros::test; use smol_macros::test;
use tytix_core::Address;
use super::*; use super::*;
@ -180,10 +194,13 @@ mod tests {
async fn check_mapping() { async fn check_mapping() {
static MSG: OnceLock<bool> = OnceLock::new(); static MSG: OnceLock<bool> = OnceLock::new();
let mut sa = SimpleAddress.map_message(|_b: Bar| { let mut sa = SimpleAddress.map(
let _ = MSG.set(true); |_b: Bar| {
async { Foo } let _ = MSG.set(true);
}); async { Foo }
},
|_a| async {},
);
sa.send(Bar).await.unwrap(); sa.send(Bar).await.unwrap();