use crate::error::LiteError;
pub fn format_sys_from(system_from_ms: i64) -> String {
format!("{system_from_ms:020}")
}
pub fn versioned_doc_key(
collection: &str,
doc_id: &str,
system_from_ms: i64,
) -> Result<Vec<u8>, LiteError> {
if doc_id.as_bytes().contains(&0) {
return Err(LiteError::BadRequest {
detail: "document id may not contain NUL byte".into(),
});
}
let s = format!(
"{collection}:{doc_id}\x00{}",
format_sys_from(system_from_ms)
);
Ok(s.into_bytes())
}
pub fn doc_prefix(collection: &str, doc_id: &str) -> Vec<u8> {
format!("{collection}:{doc_id}\x00").into_bytes()
}
pub fn doc_prefix_end(collection: &str, doc_id: &str) -> Vec<u8> {
format!("{collection}:{doc_id}\x01").into_bytes()
}
pub fn coll_prefix(collection: &str) -> Vec<u8> {
format!("{collection}:").into_bytes()
}
pub fn coll_prefix_end(collection: &str) -> Vec<u8> {
format!("{collection};").into_bytes()
}
pub fn latest_version_key(collection: &str, doc_id: &str) -> Vec<u8> {
format!("{collection}:{doc_id}").into_bytes()
}
pub fn parse_sys_from(key: &[u8]) -> Option<i64> {
let nul_pos = key.iter().rposition(|&b| b == 0)?;
let suffix = &key[nul_pos + 1..];
let s = std::str::from_utf8(suffix).ok()?;
s.parse().ok()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_ordering() {
let k1 = versioned_doc_key("coll", "doc1", 1_000).unwrap();
let k2 = versioned_doc_key("coll", "doc1", 2_000).unwrap();
assert!(k1 < k2, "earlier timestamp must sort before later");
}
#[test]
fn key_rejects_nul_doc_id() {
assert!(versioned_doc_key("coll", "bad\x00id", 1_000).is_err());
}
#[test]
fn parse_sys_from_roundtrip() {
let ms = 1_700_000_000_000_i64;
let key = versioned_doc_key("coll", "doc", ms).unwrap();
assert_eq!(parse_sys_from(&key), Some(ms));
}
#[test]
fn doc_prefix_bounds_doc_id() {
let pfx = doc_prefix("c", "d");
let pfx_end = doc_prefix_end("c", "d");
let k = versioned_doc_key("c", "d", 0).unwrap();
assert!(k >= pfx && k < pfx_end);
}
#[test]
fn coll_prefix_bounds_collection() {
let pfx = coll_prefix("c");
let pfx_end = coll_prefix_end("c");
let k1 = versioned_doc_key("c", "a", 0).unwrap();
let k2 = versioned_doc_key("c", "z", i64::MAX).unwrap();
assert!(k1 >= pfx && k1 < pfx_end);
assert!(k2 >= pfx && k2 < pfx_end);
}
}