Skip to main content

krabka_records_legacy/
message.rs

1//! v0/v1 `Message` wire format.
2//!
3//! Each message sits inside a [`MessageSet`](crate::set) entry, after the
4//! per-entry `(offset:i64, message_size:i32)` framing. The wire layout is:
5//!
6//! ```text
7//! v0: crc:u32 | magic:i8=0 | attrs:i8 |                 | key | value
8//! v1: crc:u32 | magic:i8=1 | attrs:i8 | timestamp:i64   | key | value
9//! ```
10//!
11//! `key` and `value` are nullable bytes: an i32 length, where -1 means
12//! null. The codec computes the CRC-32 (IEEE polynomial) over the bytes
13//! from `magic` through the end of `value`. That is, over everything
14//! inside the message except the CRC field itself.
15//!
16//! The magic byte and the message fields stay here. `attributes` holds the
17//! bit layout of the `attributes` byte and its compression mapping, `encode`
18//! sizes and writes a message, and `decode` parses one frame back.
19
20use {crate::error::LegacyRecordsError, bytes::Bytes, krabka_compression::CompressionType};
21
22mod attributes;
23mod decode;
24mod encode;
25
26#[cfg(test)]
27mod test_support;
28
29pub use self::attributes::{attrs, attrs_with_compression, compression_from_attrs};
30
31/// Magic byte, that is, the legacy message-format version: 0 or 1.
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub enum Magic {
34    V0,
35    V1,
36}
37
38impl Magic {
39    #[must_use]
40    pub const fn as_i8(self) -> i8 {
41        match self {
42            Self::V0 => 0,
43            Self::V1 => 1,
44        }
45    }
46
47    /// # Errors
48    /// Returns `LegacyRecordsError::UnsupportedMagic` if `b` is not 0 or 1.
49    pub fn from_i8(b: i8) -> Result<Self, LegacyRecordsError> {
50        match b {
51            0 => Ok(Self::V0),
52            1 => Ok(Self::V1),
53            other => Err(LegacyRecordsError::UnsupportedMagic { found: other }),
54        }
55    }
56}
57
58/// Owned legacy message, decoded after the frame parse.
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct Message {
61    pub magic: Magic,
62    pub attributes: i8,
63    /// `Some` when `magic` is `V1`. `None` when `magic` is `V0`.
64    pub timestamp: Option<i64>,
65    pub key: Option<Bytes>,
66    pub value: Option<Bytes>,
67}
68
69impl Message {
70    #[must_use]
71    pub fn compression(&self) -> CompressionType {
72        compression_from_attrs(self.attributes).unwrap_or(CompressionType::None)
73    }
74}