1use std::{
2 any::{type_name, Any, TypeId},
3 hash::{DefaultHasher, Hasher as _},
4 marker::PhantomData,
5 sync::Arc,
6};
7
8use crate::traits::{
9 internal::SalishMessageInternal as _, EndpointAddress, Payload, SalishMessage,
10};
11
12#[derive(Clone)]
13pub struct Message
14where
15 Self: Send + Sync,
16{
17 dest: Destination<<<Self as SalishMessage>::Endpoint as EndpointAddress>::Addr>,
18 data: Arc<Box<dyn Any + Send + Sync>>,
19 type_name: &'static str,
20}
21
22impl std::fmt::Debug for Message {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 f.debug_struct("Message")
25 .field("dest", &self.dest)
26 .field("payload_type_id", &self.payload_type())
27 .field("payload_type_name", &self.type_name)
28 .finish()
29 }
30}
31
32impl Message {
33 pub fn new<T: Payload + 'static>(data: T) -> Self {
36 Self::new_to(Destination::Any, data)
37 }
38
39 pub fn new_to<T: Payload + 'static>(
41 dest: Destination<<<Self as SalishMessage>::Endpoint as EndpointAddress>::Addr>,
42 data: T,
43 ) -> Self {
44 Self {
45 dest,
46 data: Arc::new(Box::new(data)),
47 type_name: type_name::<T>(),
48 }
49 }
50
51 pub fn is_type<T: 'static>(&self) -> bool {
53 TypeId::of::<T>() == self.payload_type()
54 }
55
56 pub fn dest(
58 &self,
59 ) -> &Destination<<<Self as SalishMessage>::Endpoint as EndpointAddress>::Addr> {
60 &self.dest
61 }
62}
63
64#[derive(Clone, Debug)]
65pub enum Destination<Addr> {
66 Any,
68
69 Endpoint(Addr),
72}
73
74impl<Addr: 'static> Destination<Addr> {
75 pub fn any() -> Self {
76 Self::Any
77 }
78
79 pub fn endpoint(addr: Addr) -> Self {
80 Self::Endpoint(addr)
81 }
82}
83
84#[derive(Debug, Clone)]
85struct HashEndpoint<'a, T>
86where
87 T: std::fmt::Debug + std::hash::Hash + Send + Sync,
88{
89 h: &'a T,
90 _phantom: PhantomData<T>,
91}
92
93impl<'a, T: std::hash::Hash> EndpointAddress for HashEndpoint<'a, T>
94where
95 T: std::fmt::Debug + std::hash::Hash + Send + Sync,
96{
97 type Addr = u64;
98 fn addr(&self) -> Self::Addr {
99 let mut hasher = DefaultHasher::new();
100 self.h.hash(&mut hasher);
101 hasher.finish()
102 }
103}
104
105impl EndpointAddress for u64 {
106 type Addr = u64;
107
108 fn addr(&self) -> Self::Addr {
109 *self
110 }
111}
112
113impl SalishMessage for Message {
114 type Endpoint = u64;
115
116 fn as_any(&self) -> &dyn Any {
118 &**self.data
119 }
120}