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