Skip to main content

amalgam/
serializers.rs

1//! Additional L2 serializers behind feature flags.
2//!
3//! The default [`JsonSerializer`](crate::JsonSerializer) lives in
4//! [`crate::distributed`]; this module hosts alternative formats.
5
6#[cfg(feature = "messagepack")]
7mod messagepack {
8    use serde::Serialize;
9    use serde::de::DeserializeOwned;
10
11    use crate::distributed::{DistributedEntry, DistributedSerializer};
12    use crate::error::{Error, Result};
13
14    /// A compact MessagePack serializer (feature `messagepack`), backed by
15    /// `rmp-serde`. A drop-in alternative to `JsonSerializer` for smaller L2
16    /// payloads.
17    #[derive(Debug, Clone, Copy, Default)]
18    pub struct MessagePackSerializer;
19
20    impl<V> DistributedSerializer<V> for MessagePackSerializer
21    where
22        V: Serialize + DeserializeOwned,
23    {
24        fn serialize(&self, entry: &DistributedEntry<V>) -> Result<Vec<u8>> {
25            rmp_serde::to_vec(entry).map_err(|e| Error::Serialization(e.to_string()))
26        }
27
28        fn deserialize(&self, bytes: &[u8]) -> Result<DistributedEntry<V>> {
29            rmp_serde::from_slice(bytes).map_err(|e| Error::Deserialization(e.to_string()))
30        }
31    }
32}
33
34#[cfg(feature = "messagepack")]
35pub use messagepack::MessagePackSerializer;
36
37#[cfg(feature = "postcard")]
38mod postcard_serializer {
39    use serde::Serialize;
40    use serde::de::DeserializeOwned;
41
42    use crate::distributed::{DistributedEntry, DistributedSerializer};
43    use crate::error::{Error, Result};
44
45    /// A compact, zero-dependency binary serializer (feature `postcard`), backed
46    /// by [`postcard`](https://docs.rs/postcard). The smallest of the built-in
47    /// formats — a good fit for high-volume L2 payloads. The same
48    /// [`DistributedSerializer`] seam accepts any other `serde` codec (bincode,
49    /// protobuf, …) just as easily.
50    #[derive(Debug, Clone, Copy, Default)]
51    pub struct PostcardSerializer;
52
53    impl<V> DistributedSerializer<V> for PostcardSerializer
54    where
55        V: Serialize + DeserializeOwned,
56    {
57        fn serialize(&self, entry: &DistributedEntry<V>) -> Result<Vec<u8>> {
58            postcard::to_allocvec(entry).map_err(|e| Error::Serialization(e.to_string()))
59        }
60
61        fn deserialize(&self, bytes: &[u8]) -> Result<DistributedEntry<V>> {
62            postcard::from_bytes(bytes).map_err(|e| Error::Deserialization(e.to_string()))
63        }
64    }
65
66    #[cfg(test)]
67    mod tests {
68        use super::*;
69
70        #[test]
71        fn round_trips_envelope() {
72            let entry = DistributedEntry {
73                value: "v".to_owned(),
74                created_ticks: 1,
75                logical_expiration_ticks: 2,
76                physical_expiration_ticks: 3,
77                is_from_fail_safe: false,
78                etag: None,
79                last_modified_ticks: None,
80                tags: vec!["t".to_owned()],
81            };
82            let ser = PostcardSerializer;
83            let bytes = DistributedSerializer::<String>::serialize(&ser, &entry).unwrap();
84            let back = DistributedSerializer::<String>::deserialize(&ser, &bytes).unwrap();
85            assert_eq!(back.value, "v");
86            assert_eq!(back.tags, vec!["t".to_owned()]);
87        }
88    }
89}
90
91#[cfg(feature = "postcard")]
92pub use postcard_serializer::PostcardSerializer;