diff --git a/crates/tytix-core/src/lib.rs b/crates/tytix-core/src/lib.rs index b65d9c4..d359c9d 100644 --- a/crates/tytix-core/src/lib.rs +++ b/crates/tytix-core/src/lib.rs @@ -41,6 +41,10 @@ impl InternalMessage { }) } + pub fn as_ref(&self) -> Option<&M> { + self.value.downcast_ref() + } + pub fn type_name(&self) -> &'static str { self.name } diff --git a/crates/tytix/src/lib.rs b/crates/tytix/src/lib.rs index fe601a6..36c4645 100644 --- a/crates/tytix/src/lib.rs +++ b/crates/tytix/src/lib.rs @@ -12,12 +12,17 @@ use tytix_core::anyhow; pub trait AddressExt { fn map_message(self, f: F) -> MappedBeforeAddress where - MB: MessageBundle, F: Fn(M) -> U + 'static, U: Future, M: Message, R: Message + IsContainedInBundle, Self: Sized; + + fn inspect(self, f: F) -> Inspect + where + F: Fn(&M) -> U, + M: Message + IsContainedInBundle, + Self: Sized; } impl> AddressExt for A { @@ -42,6 +47,48 @@ impl> AddressExt for A { _pd: PhantomData, } } + + fn inspect(self, f: F) -> Inspect + where + F: Fn(&M) -> U, + Self: Sized, + M: Message + IsContainedInBundle, + { + const { + let true = >::IS_CONTAINED else { + panic!("Message is not contained in MessageBundle",); + }; + } + + Inspect { + address: self, + func: f, + _pd: PhantomData, + } + } +} + +pub struct Inspect { + address: A, + func: F, + _pd: PhantomData U>, +} + +impl InternalMessageHandler for Inspect +where + A: InternalMessageHandler, + M: Message, + F: Fn(&M) -> U, + U: Future, +{ + type HandledMessages = A::HandledMessages; + async fn handle_message(&mut self, msg: InternalMessage) -> anyhow::Result { + if let Some(msg) = msg.as_ref() { + (self.func)(msg).await; + } + + self.address.handle_message(msg).await + } } pub struct MappedBeforeAddress { @@ -117,7 +164,7 @@ mod tests { struct SimpleAddress; impl InternalMessageHandler for SimpleAddress { - type HandledMessages = (Foo,); + type HandledMessages = (Foo, Bar); fn handle_message( &mut self, @@ -142,4 +189,22 @@ mod tests { MSG.get().expect("The message was mapped!"); } + + #[apply(test!)] + async fn check_inspect() { + static MSG: OnceLock = OnceLock::new(); + + let mut sa = SimpleAddress.inspect(|_b: &Bar| { + let _ = MSG.set(true); + async {} + }); + + sa.send(Foo).await.unwrap(); + + assert!(MSG.get().is_none()); + + sa.send(Bar).await.unwrap(); + + MSG.get().expect("The message was inspected!"); + } }