pub(crate) fn composed_len(key: &[u8]) -> usize {
1 + 2 * key.len() + 2 + 8
}
pub(crate) const WRITE: u8 = b'W';
pub(crate) const DATA: u8 = b'D';
pub(crate) const ESCAPE: u8 = 0xFF;
pub(crate) const SEP: u8 = 0x00;
fn push_escaped(key: &[u8], out: &mut Vec<u8>) {
let mut rest = key;
while let Some(at) = rest.iter().position(|&b| b == SEP) {
out.extend_from_slice(&rest[..at]);
out.push(SEP);
out.push(ESCAPE);
rest = &rest[at + 1..];
}
out.extend_from_slice(rest);
out.push(SEP);
out.push(SEP);
}
fn compose(prefix: u8, key: &[u8], ts_bytes: [u8; 8], out: &mut Vec<u8>) {
out.clear();
out.reserve(composed_len(key));
out.push(prefix);
push_escaped(key, out);
out.extend_from_slice(&ts_bytes);
}
pub(crate) fn write_key(key: &[u8], commit_ts: u64, out: &mut Vec<u8>) {
compose(WRITE, key, (!commit_ts).to_be_bytes(), out);
}
pub(crate) fn write_seek(key: &[u8], ts: u64, out: &mut Vec<u8>) {
compose(WRITE, key, (!ts).to_be_bytes(), out);
}
pub(crate) fn write_prefix(key: &[u8], out: &mut Vec<u8>) {
out.clear();
out.reserve(composed_len(key));
out.push(WRITE);
push_escaped(key, out);
}
pub(crate) fn data_key(key: &[u8], start_ts: u64, out: &mut Vec<u8>) {
compose(DATA, key, start_ts.to_be_bytes(), out);
}
pub(crate) fn user_key_of(composed: &[u8]) -> Option<Vec<u8>> {
let body = composed.strip_prefix(&[WRITE])?;
let body = body.get(..body.len().checked_sub(8)?)?;
let mut out = Vec::with_capacity(body.len());
let mut i = 0;
while i < body.len() {
if body[i] != SEP {
out.push(body[i]);
i += 1;
continue;
}
match *body.get(i + 1)? {
SEP => return (i + 2 == body.len()).then_some(out),
ESCAPE => out.push(SEP),
_ => return None,
}
i += 2;
}
None
}
pub(crate) fn commit_ts_of(write_key: &[u8]) -> Option<u64> {
let ts = write_key.get(write_key.len().checked_sub(8)?..)?;
Some(!u64::from_be_bytes(ts.try_into().ok()?))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn newer_commits_sort_before_older_ones() {
let (mut a, mut b) = (Vec::new(), Vec::new());
write_key(b"tk", 10, &mut a);
write_key(b"tk", 5, &mut b);
assert!(a < b, "a newer commit must sort first so one seek finds it");
}
#[test]
fn a_seek_lands_on_the_newest_commit_at_or_before_the_timestamp() {
let mut seek = Vec::new();
write_seek(b"tk", 7, &mut seek);
let (mut at10, mut at5) = (Vec::new(), Vec::new());
write_key(b"tk", 10, &mut at10);
write_key(b"tk", 5, &mut at5);
assert!(
at10 < seek,
"a commit after the read timestamp sorts before the seek"
);
assert!(
at5 >= seek,
"the newest commit at or before it sorts at or after"
);
}
#[test]
fn the_separator_keeps_one_key_from_being_a_prefix_of_another() {
let (mut short, mut long) = (Vec::new(), Vec::new());
write_key(b"tk", 1, &mut short);
write_key(b"tkk", 1, &mut long);
assert_ne!(short, long);
let mut prefix = Vec::new();
write_prefix(b"tk", &mut prefix);
assert!(short.starts_with(&prefix));
assert!(
!long.starts_with(&prefix),
"a longer key must not match the shorter's prefix"
);
}
#[test]
fn a_commit_timestamp_survives_the_round_trip() {
for ts in [0u64, 1, 42, u64::MAX - 1, u64::MAX] {
let mut k = Vec::new();
write_key(b"tk", ts, &mut k);
assert_eq!(commit_ts_of(&k), Some(ts), "ts {ts}");
}
}
#[test]
fn write_and_data_never_collide() {
let (mut w, mut d) = (Vec::new(), Vec::new());
write_key(b"tk", 1, &mut w);
data_key(b"tk", 1, &mut d);
assert_ne!(w, d, "the two spaces must not share a key");
assert_eq!(w[0], WRITE);
assert_eq!(d[0], DATA);
}
#[test]
fn the_buffer_is_reused_rather_than_reallocated() {
let mut buf = Vec::new();
write_key(b"tk", 1, &mut buf);
let cap = buf.capacity();
for ts in 0..64 {
write_key(b"tk", ts, &mut buf);
}
assert_eq!(buf.capacity(), cap, "composing a key must not reallocate");
}
}
#[cfg(test)]
mod nul_key_tests {
use super::*;
const AWKWARD: &[&[u8]] = &[
b"",
b"\x00",
b"\x00\x00",
b"\x00\xff",
b"\xff",
b"\xff\x00",
b"a",
b"a\x00",
b"a\x00b",
b"a\x00\x00b",
b"a\x00\xffb",
b"ab",
b"b",
];
#[test]
fn escaping_preserves_the_order_of_the_raw_keys() {
for a in AWKWARD {
for b in AWKWARD {
let (mut ca, mut cb) = (Vec::new(), Vec::new());
write_key(a, 1, &mut ca);
write_key(b, 1, &mut cb);
assert_eq!(
ca.cmp(&cb),
a.cmp(b),
"composed order disagrees with raw order for {a:?} vs {b:?}"
);
}
}
}
#[test]
fn a_user_key_survives_the_round_trip_through_a_composed_key() {
for k in AWKWARD {
let mut composed = Vec::new();
write_key(k, 7, &mut composed);
assert_eq!(
user_key_of(&composed).as_deref(),
Some(&k[..]),
"{k:?} did not survive compose then decompose"
);
assert_eq!(commit_ts_of(&composed), Some(7));
}
}
#[test]
fn user_key_of_rejects_bytes_that_are_not_a_write_record() {
let mut data = Vec::new();
data_key(b"a", 1, &mut data);
assert_eq!(
user_key_of(&data),
None,
"a data record is not a write record"
);
assert_eq!(user_key_of(b"W"), None);
assert_eq!(user_key_of(&[WRITE, b'a', 0, 0, 0, 0, 0, 0][..]), None);
}
#[test]
fn no_composed_key_is_a_prefix_of_another() {
for a in AWKWARD {
let mut prefix = Vec::new();
write_prefix(a, &mut prefix);
for b in AWKWARD {
if a == b {
continue;
}
let mut cb = Vec::new();
write_key(b, 1, &mut cb);
assert!(
!cb.starts_with(&prefix),
"key {b:?} matches key {a:?}'s prefix, so a read of {a:?} \
could return {b:?}'s value"
);
}
}
}
#[test]
fn a_key_containing_nul_is_not_confused_with_a_shorter_one() {
let (mut short, mut long) = (Vec::new(), Vec::new());
write_key(b"a", 1, &mut short);
write_key(b"a\x00b", 1, &mut long);
let mut prefix = Vec::new();
write_prefix(b"a", &mut prefix);
assert!(short.starts_with(&prefix));
assert!(
!long.starts_with(&prefix),
"key a\\0b matched key a's prefix: a read of `a` would return `a\\0b`'s value"
);
}
}