harmos_domain/message/
mod.rs1pub(crate) mod allocation;
13pub mod postcard;
14
15pub(crate) use allocation::{add as decoding_add, multiply as decoding_multiply, vector as decoding_vector};
19pub(crate) use postcard::{Reader as PostcardReader, Value as PostcardValue};
20
21use std::borrow::Cow;
25use std::collections::BTreeMap;
26macro_rules! inline_memory {
35 ($($ty:ty),* $(,)?) => {$ (
36 impl MemorySize for $ty {
37 fn memory_size(&self) -> usize {
38 std::mem::size_of::<Self>()
39 }
40 }
41 )*};
42}
43
44inline_memory!((), bool, u8, u32, u64, i32, i64, f32, f64);
45
46#[macro_export]
47macro_rules! postcard_product {
48 ($ty:ty { $($field:ident: $field_ty:ty),* $(,)? } $(, validate = $validate:expr)?) => {
49 #[allow(unused_variables)]
50 impl $crate::__private::PostcardValue for $ty {
51 fn write(&self, bytes: &mut ::std::vec::Vec<u8>) {
52 $(<$field_ty as $crate::__private::PostcardValue>::write(&self.$field, bytes);)*
53 }
54 fn size(&self) -> usize {
55 0usize$(.saturating_add(<$field_ty as $crate::__private::PostcardValue>::size(&self.$field)))*
56 }
57 fn memory(input: &mut $crate::__private::PostcardReader<'_>) -> ::std::result::Result<usize, $crate::MessageError> {
58 input.nested(|input| {
59 let memory = std::mem::size_of::<Self>();
60 $(let memory = $crate::__private::decoding_add(memory,
61 <$field_ty as $crate::__private::PostcardValue>::memory(input)?.saturating_sub(std::mem::size_of::<$field_ty>()))?;)*
62 Ok(memory)
63 })
64 }
65 fn read(input: &mut $crate::__private::PostcardReader<'_>) -> ::std::result::Result<Self, $crate::MessageError> {
66 input.nested(|input| {
67 let value = Self { $($field: <$field_ty as $crate::__private::PostcardValue>::read(input)?),* };
68 $(($validate)(&value)?;)?
69 Ok(value)
70 })
71 }
72 }
73 };
74}
75pub(crate) use postcard_product;
76
77#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
82#[error("invalid message: {0}")]
83pub struct MessageError(Cow<'static, str>);
84
85pub trait Message: Sized + Send + Sync {
90 fn encode_to_vec(&self) -> Vec<u8>;
91 fn encode_into(&self, bytes: &mut Vec<u8>) {
92 bytes.extend_from_slice(&self.encode_to_vec());
93 }
94 fn encoded_len(&self) -> usize;
95 fn decode(bytes: &[u8]) -> Result<Self, MessageError>;
96 fn decoding_memory(_bytes: &[u8]) -> Result<usize, MessageError> {
97 Err(MessageError::borrowed("decoding memory bound is unsupported"))
98 }
99}
100
101pub trait MemorySize: Sized {
102 fn memory_size(&self) -> usize;
103}
104
105pub trait Portable: Message + MemorySize + crate::schema::Described + Send + Sync + 'static {}
108
109pub trait Storable: Message + MemorySize {
110 fn encoded_size(&self) -> usize {
111 self.encoded_len()
112 }
113}
114
115impl<T> Portable for T where T: Message + MemorySize + crate::schema::Described + Send + Sync + 'static {}
118
119impl<T: PostcardValue> Message for T {
120 fn encode_to_vec(&self) -> Vec<u8> {
121 let mut bytes = Vec::with_capacity(self.size());
122 self.write(&mut bytes);
123 bytes
124 }
125 fn encode_into(&self, bytes: &mut Vec<u8>) {
126 self.write(bytes);
127 }
128 fn encoded_len(&self) -> usize {
129 self.size()
130 }
131 fn decoding_memory(bytes: &[u8]) -> Result<usize, MessageError> {
132 let mut input = PostcardReader::new(bytes);
133 let memory = Self::memory(&mut input)?;
134 input.finish()?;
135 Ok(memory)
136 }
137 fn decode(bytes: &[u8]) -> Result<Self, MessageError> {
138 <Self as Message>::decoding_memory(bytes)?;
139 let mut input = PostcardReader::new(bytes);
140 let value = Self::read(&mut input)?;
141 input.finish()?;
142 Ok(value)
143 }
144}
145
146impl<T: Message + MemorySize> Storable for T {}
147
148impl MemorySize for String {
149 fn memory_size(&self) -> usize {
150 std::mem::size_of::<Self>().saturating_add(self.capacity())
151 }
152}
153
154impl<T: MemorySize> MemorySize for Vec<T> {
155 fn memory_size(&self) -> usize {
156 let mut bytes = std::mem::size_of::<Self>().saturating_add(self.capacity().saturating_mul(std::mem::size_of::<T>()));
157
158 for value in self {
159 let owned = value.memory_size();
160 if owned == usize::MAX {
161 return usize::MAX;
162 }
163 bytes = bytes.saturating_add(owned.saturating_sub(std::mem::size_of::<T>()));
164 }
165 bytes
166 }
167}
168
169impl<T: MemorySize> MemorySize for Option<T> {
170 fn memory_size(&self) -> usize {
171 let Some(value) = self else {
172 return std::mem::size_of::<Self>();
173 };
174 let owned = value.memory_size();
175 if owned == usize::MAX {
176 return usize::MAX;
177 }
178
179 std::mem::size_of::<Self>().saturating_add(owned.saturating_sub(std::mem::size_of::<T>()))
180 }
181}
182
183impl<T: MemorySize> MemorySize for Box<T> {
185 fn memory_size(&self) -> usize {
186 let owned = (**self).memory_size();
187 if owned == usize::MAX {
188 return usize::MAX;
189 }
190
191 std::mem::size_of::<Self>().saturating_add(owned)
192 }
193}
194
195impl<K: MemorySize, V: MemorySize> MemorySize for BTreeMap<K, V> {
196 fn memory_size(&self) -> usize {
197 let mut bytes = btree_map_memory::<K, V>(self.len());
198 for (key, value) in self {
199 let key_bytes = key.memory_size();
200 let value_bytes = value.memory_size();
201 if key_bytes == usize::MAX || value_bytes == usize::MAX {
202 return usize::MAX;
203 }
204 bytes = bytes
205 .saturating_add(key_bytes.saturating_sub(std::mem::size_of::<K>()))
206 .saturating_add(value_bytes.saturating_sub(std::mem::size_of::<V>()));
207 }
208 bytes
209 }
210}
211
212impl MessageError {
213 pub fn new(reason: impl Into<String>) -> Self {
214 Self(Cow::Owned(reason.into()))
215 }
216
217 pub const fn borrowed(reason: &'static str) -> Self {
218 Self(Cow::Borrowed(reason))
219 }
220}
221
222pub fn btree_map_memory<K, V>(entries: usize) -> usize {
225 let alignment = std::mem::align_of::<K>().max(std::mem::align_of::<V>()).max(std::mem::align_of::<usize>());
226 let node = std::mem::size_of::<K>()
227 .saturating_add(std::mem::size_of::<V>())
228 .saturating_mul(11)
229 .saturating_add(13usize.saturating_mul(std::mem::size_of::<usize>()))
230 .saturating_add(2 * std::mem::size_of::<u16>())
231 .saturating_add(5usize.saturating_mul(alignment));
232 std::mem::size_of::<BTreeMap<K, V>>().saturating_add(entries.saturating_add(1).saturating_mul(node))
233}
234
235#[cfg(test)]
240mod tests {
241 use super::MemorySize;
242
243 #[test]
244 fn wrappers_saturate() {
245 struct Overflow;
246 impl MemorySize for Overflow {
247 fn memory_size(&self) -> usize {
248 usize::MAX
249 }
250 }
251
252 assert_eq!(Some(Overflow).memory_size(), usize::MAX);
253 assert_eq!(vec![Overflow].memory_size(), usize::MAX);
254 assert_eq!(Box::new(Overflow).memory_size(), usize::MAX);
255 assert_eq!(None::<Overflow>.memory_size(), std::mem::size_of::<Option<Overflow>>());
256 }
257}