1use bytes::Bytes;
4
5#[derive(Debug, thiserror::Error)]
7#[error("deserialization error: {0}")]
8pub struct SerdeError(pub String);
9
10#[diagnostic::on_unimplemented(
13 message = "the type `{Self}` is not a valid serializer/deserializer for `{T}`",
14 label = "does not implement `Serde<{T}>`",
15 note = "implement `Serde<{T}>` for `{Self}` or verify that the type parameter `{T}` matches the deserialized type of this serde"
16)]
17pub trait Serde<T>: Send + Sync + 'static {
18 fn serialize(&self, topic: &str, value: &T) -> Bytes;
19 fn deserialize(&self, topic: &str, bytes: &[u8]) -> Result<T, SerdeError>;
22
23 fn prepare(&self, _topic: &str, _role: SerdeRole) {}
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum SerdeRole {
35 Key,
36 Value,
37}
38
39#[diagnostic::on_unimplemented(
43 message = "the serde type `{Self}` is not associated with any target model type",
44 label = "does not implement `SerdeAssociate`",
45 note = "implement `SerdeAssociate` for `{Self}` and define `type Target = ...;` to map this Serde to its model type"
46)]
47pub trait SerdeAssociate {
48 type Target: Send + Sync + 'static;
49}
50
51#[derive(Debug, Clone, Copy)]
61pub struct Consumed<KS, VS> {
62 pub(crate) key_serde: KS,
63 pub(crate) value_serde: VS,
64}
65
66impl<KS, VS> Consumed<KS, VS> {
67 #[must_use]
70 pub fn with(key_serde: KS, value_serde: VS) -> Self {
71 Self {
72 key_serde,
73 value_serde,
74 }
75 }
76}
77
78#[derive(Debug, Clone, Copy)]
87pub struct Produced<KS, VS> {
88 pub(crate) key_serde: KS,
89 pub(crate) value_serde: VS,
90}
91
92impl<KS, VS> Produced<KS, VS> {
93 #[must_use]
96 pub fn with(key_serde: KS, value_serde: VS) -> Self {
97 Self {
98 key_serde,
99 value_serde,
100 }
101 }
102}
103
104pub(crate) struct SerdeArc<T>(pub(crate) std::sync::Arc<dyn Serde<T>>);
111
112impl<T> Clone for SerdeArc<T> {
113 fn clone(&self) -> Self {
114 SerdeArc(std::sync::Arc::clone(&self.0))
115 }
116}
117
118impl<T: Send + Sync + 'static> Serde<T> for SerdeArc<T> {
119 fn serialize(&self, topic: &str, value: &T) -> Bytes {
120 self.0.serialize(topic, value)
121 }
122 fn deserialize(&self, topic: &str, bytes: &[u8]) -> Result<T, SerdeError> {
123 self.0.deserialize(topic, bytes)
124 }
125 fn prepare(&self, topic: &str, role: SerdeRole) {
126 self.0.prepare(topic, role);
127 }
128}
129
130impl<T: Send + Sync + 'static> SerdeAssociate for SerdeArc<T> {
131 type Target = T;
132}
133
134#[derive(Debug, Clone, Copy, Default)]
136pub struct BytesSerde;
137impl Serde<Bytes> for BytesSerde {
138 fn serialize(&self, _topic: &str, value: &Bytes) -> Bytes {
139 value.clone()
140 }
141 fn deserialize(&self, _topic: &str, bytes: &[u8]) -> Result<Bytes, SerdeError> {
142 Ok(Bytes::copy_from_slice(bytes))
143 }
144}
145
146impl SerdeAssociate for BytesSerde {
147 type Target = Bytes;
148}
149
150#[derive(Debug, Clone, Copy, Default)]
152pub struct StringSerde;
153impl Serde<String> for StringSerde {
154 fn serialize(&self, _topic: &str, value: &String) -> Bytes {
155 Bytes::copy_from_slice(value.as_bytes())
156 }
157 fn deserialize(&self, _topic: &str, bytes: &[u8]) -> Result<String, SerdeError> {
158 String::from_utf8(bytes.to_vec()).map_err(|e| SerdeError(e.to_string()))
159 }
160}
161
162impl SerdeAssociate for StringSerde {
163 type Target = String;
164}
165
166#[derive(Debug, Clone, Copy, Default)]
168pub struct I64Serde;
169impl Serde<i64> for I64Serde {
170 fn serialize(&self, _topic: &str, value: &i64) -> Bytes {
171 Bytes::copy_from_slice(&value.to_be_bytes())
172 }
173 fn deserialize(&self, _topic: &str, bytes: &[u8]) -> Result<i64, SerdeError> {
174 let arr: [u8; 8] = bytes
175 .try_into()
176 .map_err(|_| SerdeError(format!("expected 8 bytes, got {}", bytes.len())))?;
177 Ok(i64::from_be_bytes(arr))
178 }
179}
180
181impl SerdeAssociate for I64Serde {
182 type Target = i64;
183}
184
185#[diagnostic::on_unimplemented(
202 message = "the type `{Self}` does not have a default Serde implementation",
203 label = "no default Serde association found for this type",
204 note = "implement `DefaultSerde` for `{Self}` or specify/override the serde explicitly using `.with_key_serde()` or `.with_value_serde()`"
205)]
206pub trait DefaultSerde: Send + Sync + 'static + Sized {
207 type Serde: SerdeAssociate<Target = Self> + Serde<Self> + Clone + Default + 'static;
208}
209
210impl DefaultSerde for String {
211 type Serde = StringSerde;
212}
213
214impl DefaultSerde for i64 {
215 type Serde = I64Serde;
216}
217
218impl DefaultSerde for bytes::Bytes {
219 type Serde = BytesSerde;
220}
221
222impl<KS, VS> From<(KS, VS)> for Consumed<KS, VS> {
223 fn from((key_serde, value_serde): (KS, VS)) -> Self {
224 Self::with(key_serde, value_serde)
225 }
226}
227
228impl<KS, VS> From<(KS, VS)> for Produced<KS, VS> {
229 fn from((key_serde, value_serde): (KS, VS)) -> Self {
230 Self::with(key_serde, value_serde)
231 }
232}
233
234fn write_varint(n: usize, buf: &mut Vec<u8>) {
241 let mut v = (n as u64) << 1;
244 loop {
245 if v < 0x80 {
246 buf.push(v.to_le_bytes()[0]);
247 break;
248 }
249 buf.push(v.to_le_bytes()[0] | 0x80);
250 v >>= 7;
251 }
252}
253
254fn read_varint(bytes: &[u8]) -> Result<(usize, usize), SerdeError> {
258 let mut value: u64 = 0;
259 let mut shift = 0u32;
260 let mut consumed = 0;
261 for &b in bytes {
262 consumed += 1;
263 let low7 = u64::from(b & 0x7F);
264 value |= low7 << shift;
265 shift += 7;
266 if b & 0x80 == 0 {
267 let decoded = (value >> 1) ^ ((value & 1).wrapping_neg());
269 let n = usize::try_from(decoded)
270 .map_err(|_| SerdeError(format!("varint value {decoded} out of usize range")))?;
271 return Ok((n, consumed));
272 }
273 if shift >= 64 {
274 return Err(SerdeError("varint overflow".to_string()));
275 }
276 }
277 Err(SerdeError("truncated varint".to_string()))
278}
279
280#[derive(Debug, Clone, Copy)]
294pub struct Changed<S> {
295 inner: S,
296}
297
298impl<S> Changed<S> {
299 #[must_use]
301 pub fn new(inner: S) -> Self {
302 Self { inner }
303 }
304}
305
306impl<V, S> Serde<crate::dsl::processors::change::Change<V>> for Changed<S>
307where
308 V: Send + Sync + 'static,
309 S: Serde<V>,
310{
311 fn serialize(&self, topic: &str, value: &crate::dsl::processors::change::Change<V>) -> Bytes {
312 match (&value.new, &value.old) {
313 (Some(new), Some(old)) => {
314 let new_bytes = self.inner.serialize(topic, new);
315 let old_bytes = self.inner.serialize(topic, old);
316 let mut buf = Vec::with_capacity(1 + new_bytes.len() + old_bytes.len() + 1);
317 write_varint(new_bytes.len(), &mut buf);
318 buf.extend_from_slice(&new_bytes);
319 buf.extend_from_slice(&old_bytes);
320 buf.push(0x02);
321 Bytes::from(buf)
322 }
323 (Some(new), None) => {
324 let new_bytes = self.inner.serialize(topic, new);
325 let mut buf = Vec::with_capacity(new_bytes.len() + 1);
326 buf.extend_from_slice(&new_bytes);
327 buf.push(0x01);
328 Bytes::from(buf)
329 }
330 (None, Some(old)) => {
331 let old_bytes = self.inner.serialize(topic, old);
332 let mut buf = Vec::with_capacity(old_bytes.len() + 1);
333 buf.extend_from_slice(&old_bytes);
334 buf.push(0x00);
335 Bytes::from(buf)
336 }
337 (None, None) => unreachable!("Changed serde never carries a both-None change"),
342 }
343 }
344
345 fn deserialize(
346 &self,
347 topic: &str,
348 bytes: &[u8],
349 ) -> Result<crate::dsl::processors::change::Change<V>, SerdeError> {
350 if bytes.is_empty() {
351 return Err(SerdeError("empty bytes for Change".to_string()));
352 }
353 let flag = bytes[bytes.len() - 1];
354 let payload = &bytes[..bytes.len() - 1];
355 match flag {
356 0x00 => {
357 let old = self.inner.deserialize(topic, payload)?;
358 Ok(crate::dsl::processors::change::Change {
359 old: Some(old),
360 new: None,
361 })
362 }
363 0x01 => {
364 let new = self.inner.deserialize(topic, payload)?;
365 Ok(crate::dsl::processors::change::Change {
366 old: None,
367 new: Some(new),
368 })
369 }
370 0x02 => {
371 let (new_len, consumed) = read_varint(payload)?;
372 let after_varint = &payload[consumed..];
373 if after_varint.len() < new_len {
374 return Err(SerdeError(format!(
375 "not enough bytes for new value: need {new_len}, have {}",
376 after_varint.len()
377 )));
378 }
379 let new_bytes = &after_varint[..new_len];
380 let old_bytes = &after_varint[new_len..];
381 let new = self.inner.deserialize(topic, new_bytes)?;
382 let old = self.inner.deserialize(topic, old_bytes)?;
383 Ok(crate::dsl::processors::change::Change {
384 old: Some(old),
385 new: Some(new),
386 })
387 }
388 other => Err(SerdeError(format!("unknown Change flag: 0x{other:02x}"))),
389 }
390 }
391}
392
393#[cfg(test)]
394mod tests {
395 use assert2::check;
396
397 use super::*;
398
399 #[test]
400 fn string_serde_round_trips() {
401 let s = StringSerde;
402 let b = s.serialize("t", &"héllo".to_string());
403 check!(s.deserialize("t", &b).unwrap() == "héllo");
404 }
405
406 #[test]
407 fn i64_serde_is_big_endian_8_bytes() {
408 let s = I64Serde;
409 let b = s.serialize("t", &1i64);
410 check!(b.as_ref() == [0, 0, 0, 0, 0, 0, 0, 1]);
411 check!(s.deserialize("t", &b).unwrap() == 1);
412 check!(s.deserialize("t", &[0, 1]).is_err());
413 }
414
415 #[test]
416 fn bytes_serde_is_identity() {
417 let s = BytesSerde;
418 let b = s.serialize("t", &bytes::Bytes::from_static(b"xy"));
419 check!(s.deserialize("t", &b).unwrap() == bytes::Bytes::from_static(b"xy"));
420 }
421
422 fn hex(b: &[u8]) -> String {
423 b.iter().fold(String::new(), |mut s, x| {
424 use std::fmt::Write as _;
425 write!(s, "{x:02x}").unwrap();
426 s
427 })
428 }
429
430 fn golden() -> serde_json::Value {
431 let base = std::env::var("CARGO_MANIFEST_DIR")
437 .unwrap_or_else(|_| "crates/client-streams".to_owned());
438 let path =
439 std::path::Path::new(&base).join("tests/testdata/kgrouped_table/changed_bytes.json");
440 let raw = std::fs::read_to_string(&path).unwrap_or_else(|error| {
441 panic!("read changed_bytes golden {}: {error}", path.display())
442 });
443 serde_json::from_str(&raw).unwrap()
444 }
445
446 #[test]
447 fn changed_long_matches_jvm_bytes() {
448 let g = golden();
449 let s = Changed::new(I64Serde);
450 let both = crate::dsl::processors::change::Change {
451 old: Some(2i64),
452 new: Some(6i64),
453 };
454 let new_only = crate::dsl::processors::change::Change {
455 old: None,
456 new: Some(5i64),
457 };
458 let old_only = crate::dsl::processors::change::Change {
459 old: Some(4i64),
460 new: None,
461 };
462 check!(hex(&s.serialize("topic", &both)) == g["both"].as_str().unwrap());
463 check!(hex(&s.serialize("topic", &new_only)) == g["new_only"].as_str().unwrap());
464 check!(hex(&s.serialize("topic", &old_only)) == g["old_only"].as_str().unwrap());
465 }
466
467 #[test]
468 fn changed_round_trips() {
469 let s = Changed::new(I64Serde);
470 for c in [
471 crate::dsl::processors::change::Change {
472 old: Some(2i64),
473 new: Some(6i64),
474 },
475 crate::dsl::processors::change::Change {
476 old: None,
477 new: Some(5i64),
478 },
479 crate::dsl::processors::change::Change {
480 old: Some(4i64),
481 new: None,
482 },
483 ] {
484 let bytes = s.serialize("topic", &c);
485 let back: crate::dsl::processors::change::Change<i64> =
486 s.deserialize("topic", &bytes).unwrap();
487 check!(back == c);
488 }
489 }
490}