Skip to main content

elfo_core/
message.rs

1use std::{
2    alloc, fmt,
3    ptr::{self, NonNull},
4};
5
6use metrics::Label;
7use serde::{Deserialize, Serialize};
8use smallbox::smallbox;
9
10use crate::dumping;
11
12pub use self::{any::*, lookup::*, protocol::*, repr::*};
13
14mod any;
15mod lookup;
16mod protocol;
17mod repr;
18
19// === Message ===
20
21/// Represents a message that can be sent between actors and across nodes.
22///
23/// Never implement it by hand, use the `#[message]` macro instead.
24pub trait Message:
25    fmt::Debug + Clone + Send + Serialize + for<'de> Deserialize<'de> + 'static
26{
27    #[inline(always)]
28    fn name(&self) -> &'static str {
29        self._vtable().name
30    }
31
32    #[inline(always)]
33    fn protocol(&self) -> &'static str {
34        self._vtable().protocol
35    }
36
37    #[doc(hidden)] // unstable because depends on `metrics`
38    #[inline(always)]
39    fn labels(&self) -> &'static [Label] {
40        &self._vtable().labels
41    }
42
43    #[doc(hidden)] // unstable because will be replaced with `DumpingMode`
44    #[inline(always)]
45    fn dumping_allowed(&self) -> bool {
46        self._vtable().dumping_allowed
47    }
48
49    // Private API.
50
51    #[doc(hidden)]
52    fn _type_id() -> MessageTypeId;
53
54    #[doc(hidden)]
55    fn _vtable(&self) -> &'static MessageVTable;
56
57    #[doc(hidden)]
58    #[inline(always)]
59    fn _repr_layout(&self) -> alloc::Layout {
60        self._vtable().repr_layout
61    }
62
63    // NOTE: All methods below MUST be overriden for `AnyMessage`.
64
65    #[doc(hidden)]
66    #[inline(always)]
67    fn _is_supertype_of(type_id: MessageTypeId) -> bool {
68        Self::_type_id() == type_id
69    }
70
71    #[doc(hidden)]
72    #[inline(always)]
73    fn _into_any(self) -> AnyMessage {
74        AnyMessage::from_real(self)
75    }
76
77    /// # Safety
78    ///
79    /// The caller must ensure that `any` holds this message type.
80    #[doc(hidden)]
81    #[inline(always)]
82    unsafe fn _from_any(any: AnyMessage) -> Self {
83        any.into_real()
84    }
85
86    /// # Safety
87    ///
88    /// The caller must ensure that `any` holds this message type.
89    #[doc(hidden)]
90    #[inline(always)]
91    unsafe fn _from_any_ref(any: &AnyMessage) -> &Self {
92        any.as_real_ref()
93    }
94
95    /// # Safety
96    ///
97    /// The caller must ensure that `any` holds this message type.
98    #[doc(hidden)]
99    #[inline(always)]
100    unsafe fn _from_any_mut(any: &mut AnyMessage) -> &mut Self {
101        any.as_real_mut()
102    }
103
104    #[doc(hidden)]
105    #[inline(always)]
106    fn _erase(&self) -> dumping::ErasedMessage {
107        smallbox!(self.clone())
108    }
109
110    /// # Safety
111    ///
112    /// Behavior is undefined if any of the following conditions are violated:
113    /// * `ptr` must be [valid] for reads.
114    /// * `ptr` must point to a properly initialized value of type `Self`.
115    /// * Data behind `ptr` must not be used after this function is called.
116    ///
117    /// [valid]: https://doc.rust-lang.org/stable/std/ptr/index.html#safety
118    #[doc(hidden)]
119    #[inline(always)]
120    unsafe fn _read(ptr: NonNull<MessageRepr>) -> Self {
121        let data_ref = &ptr.cast::<MessageRepr<Self>>().as_ref().data;
122        ptr::read(data_ref)
123    }
124
125    /// # Safety
126    ///
127    /// Behavior is undefined if any of the following conditions are violated:
128    /// * `ptr` must be [valid] for writes.
129    /// * `ptr` must be properly aligned.
130    ///
131    /// [valid]: https://doc.rust-lang.org/stable/std/ptr/index.html#safety
132    #[doc(hidden)]
133    #[inline(always)]
134    unsafe fn _write(self, ptr: NonNull<MessageRepr>) {
135        let repr = MessageRepr::new(self);
136        ptr::write(ptr.cast::<MessageRepr<Self>>().as_ptr(), repr);
137    }
138}
139
140// === Request ===
141
142/// Represents a request that can be sent between actors and across nodes.
143///
144/// Never implement it by hand, use the `#[message(ret = ...)]` macro instead.
145pub trait Request: Message {
146    type Response; // constraints are checked by `Wrapper`
147
148    /// Generated by `#[message(ret = ...)]`.
149    /// It allows to use `!Message` such as `Result<T, E>`, `Option<T>` etc.
150    #[doc(hidden)]
151    type Wrapper: Message + Into<Self::Response> + From<Self::Response>;
152}