use std::sync::Arc;
pub trait ActorMessage: Send + Sync + 'static {}
pub trait CloneableMessage: ActorMessage + Clone {}
pub struct SharedMessage<M> {
inner: Arc<M>,
}
impl<M> Clone for SharedMessage<M> {
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
}
}
}
impl<M> SharedMessage<M> {
pub fn new(msg: M) -> Self {
Self {
inner: Arc::new(msg),
}
}
pub fn inner(&self) -> &M {
&self.inner
}
pub fn into_inner(self) -> Arc<M> {
self.inner
}
}
impl<M: Send + Sync + 'static> ActorMessage for SharedMessage<M> {}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[derive(Debug, Clone, PartialEq)]
struct TestMessage {
content: String,
}
impl ActorMessage for TestMessage {}
impl CloneableMessage for TestMessage {}
#[derive(Debug, PartialEq)]
struct NonCloneableMessage {
data: String,
}
impl ActorMessage for NonCloneableMessage {}
#[test]
fn test_shared_message_creation() {
let msg = TestMessage {
content: "test".to_string(),
};
let shared = SharedMessage::new(msg);
assert_eq!(shared.inner().content, "test");
}
#[test]
fn test_shared_message_clone() {
let msg = TestMessage {
content: "original".to_string(),
};
let shared1 = SharedMessage::new(msg);
let shared2 = shared1.clone();
assert_eq!(shared1.inner().content, shared2.inner().content);
assert_eq!(shared1.inner().content, "original");
assert_eq!(Arc::strong_count(&shared1.inner), 2);
assert_eq!(Arc::strong_count(&shared2.inner), 2);
}
#[test]
fn test_shared_message_into_inner() {
let msg = TestMessage {
content: "into_inner_test".to_string(),
};
let shared = SharedMessage::new(msg);
let arc = shared.into_inner();
assert_eq!(arc.content, "into_inner_test");
assert_eq!(Arc::strong_count(&arc), 1);
}
#[test]
fn test_shared_message_inner_reference() {
let msg = TestMessage {
content: "reference_test".to_string(),
};
let shared = SharedMessage::new(msg);
let inner_ref = shared.inner();
assert_eq!(inner_ref.content, "reference_test");
}
#[test]
fn test_shared_message_with_non_cloneable() {
let msg = NonCloneableMessage {
data: "non_cloneable".to_string(),
};
let shared1 = SharedMessage::new(msg);
let shared2 = shared1.clone();
assert_eq!(shared1.inner().data, "non_cloneable");
assert_eq!(shared2.inner().data, "non_cloneable");
}
#[test]
fn test_actor_message_trait_implemented() {
let msg = TestMessage {
content: "trait_test".to_string(),
};
let shared = SharedMessage::new(msg);
fn accepts_actor_message<T: ActorMessage>(_: T) {}
accepts_actor_message(shared);
}
#[test]
fn test_cloneable_message_trait() {
let msg = TestMessage {
content: "cloneable_test".to_string(),
};
fn accepts_cloneable_message<T: CloneableMessage>(_: T) {}
accepts_cloneable_message(msg);
}
#[test]
fn test_shared_message_debug() {
let msg = TestMessage {
content: "debug_test".to_string(),
};
let shared = SharedMessage::new(msg);
let debug_str = format!("{:?}", shared.inner());
assert!(debug_str.contains("debug_test"));
}
#[test]
fn test_multiple_shared_message_clones() {
let msg = TestMessage {
content: "multi_clone_test".to_string(),
};
let shared1 = SharedMessage::new(msg);
let shared2 = shared1.clone();
let shared3 = shared2.clone();
let shared4 = shared1.clone();
assert_eq!(shared1.inner().content, "multi_clone_test");
assert_eq!(shared2.inner().content, "multi_clone_test");
assert_eq!(shared3.inner().content, "multi_clone_test");
assert_eq!(shared4.inner().content, "multi_clone_test");
assert_eq!(Arc::strong_count(&shared1.inner), 4);
}
#[test]
fn test_shared_message_arc_cleanup() {
let msg = TestMessage {
content: "cleanup_test".to_string(),
};
let shared1 = SharedMessage::new(msg);
let shared2 = shared1.clone();
assert_eq!(Arc::strong_count(&shared1.inner), 2);
drop(shared2);
assert_eq!(Arc::strong_count(&shared1.inner), 1);
drop(shared1);
}
}