pub const SEP: u8 = 0x00;
pub fn offset_key(topic: &str) -> Vec<u8> {
let mut k = Vec::with_capacity(topic.len() + 6);
k.extend_from_slice(topic.as_bytes());
k.push(SEP);
k.extend_from_slice(b"head");
k
}
pub fn offset_prefix(topic: &str) -> Vec<u8> {
let mut k = Vec::with_capacity(topic.len() + 1);
k.extend_from_slice(topic.as_bytes());
k.push(SEP);
k
}
pub fn log_key(topic: &str, offset: i64) -> Vec<u8> {
let mut k = Vec::with_capacity(topic.len() + 22);
k.extend_from_slice(topic.as_bytes());
k.push(SEP);
k.extend_from_slice(format!("{offset:020}").as_bytes());
k
}
pub fn log_prefix(topic: &str) -> Vec<u8> {
let mut k = Vec::with_capacity(topic.len() + 1);
k.extend_from_slice(topic.as_bytes());
k.push(SEP);
k
}
pub fn log_range_start(topic: &str, from: i64) -> Vec<u8> {
log_key(topic, from)
}
pub fn log_range_end(topic: &str, to: i64) -> Vec<u8> {
let mut k = log_key(topic, to);
k.push(0xFF);
k
}
pub fn dedupe_key(topic: &str, message_id: &str) -> Vec<u8> {
let mut k = Vec::with_capacity(topic.len() + 1 + message_id.len() + 1);
k.extend_from_slice(topic.as_bytes());
k.push(SEP);
k.extend_from_slice(message_id.as_bytes());
k.push(SEP);
k
}
pub fn dedupe_prefix(topic: &str) -> Vec<u8> {
let mut k = Vec::with_capacity(topic.len() + 1);
k.extend_from_slice(topic.as_bytes());
k.push(SEP);
k
}
pub fn snapshot_key(topic: &str, snapshot_id: &str) -> Vec<u8> {
let mut k = Vec::with_capacity(topic.len() + 1 + snapshot_id.len());
k.extend_from_slice(topic.as_bytes());
k.push(SEP);
k.extend_from_slice(snapshot_id.as_bytes());
k
}
pub fn snapshot_prefix(topic: &str) -> Vec<u8> {
let mut k = Vec::with_capacity(topic.len() + 1);
k.extend_from_slice(topic.as_bytes());
k.push(SEP);
k
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn offset_key_has_separator() {
let k = offset_key("room/5");
assert!(k.windows(2).any(|w| w == [b'/', b'5']));
assert!(k.contains(&SEP));
}
#[test]
fn log_key_sort_order() {
let k1 = log_key("t", 9);
let k2 = log_key("t", 10);
let k3 = log_key("t", 100);
assert!(k1 < k2);
assert!(k2 < k3);
}
#[test]
fn log_key_topic_isolation() {
let k_a = log_prefix("room/5");
let k_b = log_prefix("room/50");
let room5_key = log_key("room/5", 1);
assert!(room5_key.starts_with(&k_a));
assert!(!room5_key.starts_with(&k_b));
}
#[test]
fn dedupe_prefix_isolation() {
let p = dedupe_prefix("t");
let k = dedupe_key("t", "msg-1");
assert!(k.starts_with(&p));
}
#[test]
fn snapshot_key_round_trip() {
let k = snapshot_key("room/1", "snap-abc");
let p = snapshot_prefix("room/1");
assert!(k.starts_with(&p));
}
}