dynamo_runtime/transports/event_plane/
codec.rs1use anyhow::Result;
7use bytes::Bytes;
8use serde::{Serialize, de::DeserializeOwned};
9
10use super::EventEnvelope;
11
12#[derive(Debug, Clone, Copy)]
16pub enum Codec {
17 Msgpack(MsgpackCodec),
18}
19
20impl Default for Codec {
21 fn default() -> Self {
22 Codec::Msgpack(MsgpackCodec)
23 }
24}
25
26impl Codec {
27 pub fn encode_envelope(&self, envelope: &EventEnvelope) -> Result<Bytes> {
29 match self {
30 Codec::Msgpack(c) => c.encode_envelope(envelope),
31 }
32 }
33
34 pub fn encode_envelope_parts(
36 &self,
37 publisher_id: u64,
38 sequence: u64,
39 published_at: u64,
40 topic: &str,
41 payload: &[u8],
42 ) -> Result<Bytes> {
43 match self {
44 Codec::Msgpack(c) => {
45 c.encode_envelope_parts(publisher_id, sequence, published_at, topic, payload)
46 }
47 }
48 }
49
50 pub fn decode_envelope(&self, bytes: &Bytes) -> Result<EventEnvelope> {
52 match self {
53 Codec::Msgpack(c) => c.decode_envelope(bytes),
54 }
55 }
56
57 pub fn encode_payload<T: Serialize>(&self, payload: &T) -> Result<Bytes> {
59 match self {
60 Codec::Msgpack(c) => c.encode_payload(payload),
61 }
62 }
63
64 pub fn decode_payload<T: DeserializeOwned>(&self, bytes: &Bytes) -> Result<T> {
66 match self {
67 Codec::Msgpack(c) => c.decode_payload(bytes),
68 }
69 }
70
71 pub fn name(&self) -> &'static str {
73 match self {
74 Codec::Msgpack(c) => c.name(),
75 }
76 }
77}
78
79#[derive(Debug, Clone, Copy, Default)]
80pub struct MsgpackCodec;
81
82#[derive(Serialize)]
83struct BorrowedEventEnvelope<'a> {
84 publisher_id: u64,
85 sequence: u64,
86 published_at: u64,
87 topic: &'a str,
88 #[serde(serialize_with = "serialize_bytes")]
89 payload: &'a [u8],
90}
91
92fn serialize_bytes<S>(bytes: &&[u8], serializer: S) -> std::result::Result<S::Ok, S::Error>
93where
94 S: serde::Serializer,
95{
96 serializer.serialize_bytes(bytes)
97}
98
99impl MsgpackCodec {
100 pub fn encode_envelope(&self, envelope: &EventEnvelope) -> Result<Bytes> {
101 Ok(Bytes::from(rmp_serde::to_vec_named(envelope)?))
102 }
103
104 pub fn encode_envelope_parts(
105 &self,
106 publisher_id: u64,
107 sequence: u64,
108 published_at: u64,
109 topic: &str,
110 payload: &[u8],
111 ) -> Result<Bytes> {
112 let envelope = BorrowedEventEnvelope {
113 publisher_id,
114 sequence,
115 published_at,
116 topic,
117 payload,
118 };
119 Ok(Bytes::from(rmp_serde::to_vec_named(&envelope)?))
120 }
121
122 pub fn decode_envelope(&self, bytes: &Bytes) -> Result<EventEnvelope> {
123 Ok(rmp_serde::from_slice(bytes)?)
124 }
125
126 pub fn encode_payload<T: Serialize>(&self, payload: &T) -> Result<Bytes> {
127 Ok(Bytes::from(rmp_serde::to_vec_named(payload)?))
128 }
129
130 pub fn decode_payload<T: DeserializeOwned>(&self, bytes: &Bytes) -> Result<T> {
131 Ok(rmp_serde::from_slice(bytes)?)
132 }
133
134 pub fn name(&self) -> &'static str {
135 "msgpack"
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[derive(Debug, Clone, PartialEq, Serialize, serde::Deserialize)]
144 struct TestEvent {
145 worker_id: u64,
146 message: String,
147 }
148
149 #[test]
150 fn test_msgpack_codec_envelope_roundtrip() {
151 let codec = MsgpackCodec;
152
153 let envelope = EventEnvelope {
154 publisher_id: 12345,
155 sequence: 42,
156 published_at: 1700000000000,
157 topic: "test-topic".to_string(),
158 payload: Bytes::from("test payload"),
159 };
160
161 let encoded = codec.encode_envelope(&envelope).unwrap();
162 let decoded = codec.decode_envelope(&encoded).unwrap();
163
164 assert_eq!(decoded.publisher_id, envelope.publisher_id);
165 assert_eq!(decoded.sequence, envelope.sequence);
166 assert_eq!(decoded.published_at, envelope.published_at);
167 assert_eq!(decoded.topic, envelope.topic);
168 assert_eq!(decoded.payload, envelope.payload);
169 }
170
171 #[test]
172 fn test_msgpack_codec_borrowed_envelope_roundtrip() {
173 let codec = MsgpackCodec;
174 let payload = b"borrowed payload";
175
176 let borrowed = codec
177 .encode_envelope_parts(12345, 42, 1700000000000, "test-topic", payload)
178 .unwrap();
179 let owned = codec
180 .encode_envelope(&EventEnvelope {
181 publisher_id: 12345,
182 sequence: 42,
183 published_at: 1700000000000,
184 topic: "test-topic".to_string(),
185 payload: Bytes::from_static(payload),
186 })
187 .unwrap();
188 assert_eq!(borrowed, owned);
189
190 let decoded: EventEnvelope = rmp_serde::from_slice(&borrowed).unwrap();
191
192 assert_eq!(decoded.publisher_id, 12345);
193 assert_eq!(decoded.sequence, 42);
194 assert_eq!(decoded.published_at, 1700000000000);
195 assert_eq!(decoded.topic, "test-topic");
196 assert_eq!(decoded.payload.as_ref(), payload);
197 }
198
199 #[test]
200 fn test_msgpack_codec_payload_roundtrip() {
201 let codec = MsgpackCodec;
202
203 let event = TestEvent {
204 worker_id: 123,
205 message: "hello world".to_string(),
206 };
207
208 let encoded = codec.encode_payload(&event).unwrap();
209 let decoded: TestEvent = codec.decode_payload(&encoded).unwrap();
210
211 assert_eq!(decoded, event);
212 }
213}