pub fn prefix_end(prefix: impl AsRef<[u8]>) -> Option<Vec<u8>> {
let prefix = prefix.as_ref();
if prefix.is_empty() {
return None;
}
let mut end = prefix.to_vec();
while let Some(last) = end.last_mut() {
if *last == u8::MAX {
end.pop();
} else {
*last += 1;
return Some(end);
}
}
None
}
pub fn prefix_range(prefix: impl AsRef<[u8]>) -> (Vec<u8>, Option<Vec<u8>>) {
let start = prefix.as_ref().to_vec();
let end = prefix_end(&start);
(start, end)
}
pub fn u64_key(value: u64) -> [u8; 8] {
value.to_be_bytes()
}
pub fn u128_key(value: u128) -> [u8; 16] {
value.to_be_bytes()
}
pub fn i64_key(value: i64) -> [u8; 8] {
((value as u64) ^ (1u64 << 63)).to_be_bytes()
}
pub fn i128_key(value: i128) -> [u8; 16] {
((value as u128) ^ (1u128 << 127)).to_be_bytes()
}
pub fn timestamp_millis_key(value: u64) -> [u8; 8] {
u64_key(value)
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct KeyBuilder {
bytes: Vec<u8>,
}
impl KeyBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
bytes: Vec::with_capacity(capacity),
}
}
pub fn from_prefix(prefix: impl Into<Vec<u8>>) -> Self {
Self {
bytes: prefix.into(),
}
}
pub fn push_raw(mut self, bytes: impl AsRef<[u8]>) -> Self {
self.bytes.extend_from_slice(bytes.as_ref());
self
}
pub fn push_segment(mut self, segment: impl AsRef<[u8]>) -> Self {
encode_segment_into(segment.as_ref(), &mut self.bytes);
self
}
pub fn push_str(self, segment: &str) -> Self {
self.push_segment(segment.as_bytes())
}
pub fn push_u64(self, value: u64) -> Self {
self.push_segment(u64_key(value))
}
pub fn push_u128(self, value: u128) -> Self {
self.push_segment(u128_key(value))
}
pub fn push_i64(self, value: i64) -> Self {
self.push_segment(i64_key(value))
}
pub fn push_i128(self, value: i128) -> Self {
self.push_segment(i128_key(value))
}
pub fn push_timestamp_millis(self, value: u64) -> Self {
self.push_segment(timestamp_millis_key(value))
}
pub fn as_slice(&self) -> &[u8] {
&self.bytes
}
pub fn finish(self) -> Vec<u8> {
self.bytes
}
}
pub fn encode_segment(segment: impl AsRef<[u8]>) -> Vec<u8> {
let mut out = Vec::with_capacity(segment.as_ref().len() + 2);
encode_segment_into(segment.as_ref(), &mut out);
out
}
pub fn encode_segment_prefix(segment: impl AsRef<[u8]>) -> Vec<u8> {
let segment = segment.as_ref();
let mut out = Vec::with_capacity(segment.len());
for byte in segment {
if *byte == 0 {
out.extend_from_slice(&[0x00, 0xff]);
} else {
out.push(*byte);
}
}
out
}
pub fn decode_segments(key: &[u8]) -> Result<Vec<Vec<u8>>, KeyDecodeError> {
let mut segments = Vec::new();
let mut current = Vec::new();
let mut offset = 0usize;
while offset < key.len() {
let byte = key[offset];
if byte != 0 {
current.push(byte);
offset += 1;
continue;
}
let Some(marker) = key.get(offset + 1).copied() else {
return Err(KeyDecodeError::UnexpectedEnd { offset });
};
match marker {
0x00 => {
segments.push(std::mem::take(&mut current));
offset += 2;
}
0xff => {
current.push(0);
offset += 2;
}
marker => {
return Err(KeyDecodeError::InvalidEscape { offset, marker });
}
}
}
if current.is_empty() {
Ok(segments)
} else {
Err(KeyDecodeError::UnexpectedEnd { offset: key.len() })
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum KeyDecodeError {
UnexpectedEnd { offset: usize },
InvalidEscape { offset: usize, marker: u8 },
}
impl std::fmt::Display for KeyDecodeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnexpectedEnd { offset } => {
write!(f, "encoded key ended unexpectedly at byte offset {offset}")
}
Self::InvalidEscape { offset, marker } => write!(
f,
"invalid encoded key escape at byte offset {offset}: 0x{marker:02x}"
),
}
}
}
impl std::error::Error for KeyDecodeError {}
pub fn debug_key(key: &[u8]) -> String {
let mut out = String::with_capacity(key.len().saturating_add(2));
out.push('"');
for byte in key {
match *byte {
b'\\' => out.push_str("\\\\"),
b'"' => out.push_str("\\\""),
b'\n' => out.push_str("\\n"),
b'\r' => out.push_str("\\r"),
b'\t' => out.push_str("\\t"),
0x20..=0x7e => out.push(*byte as char),
byte => out.push_str(&format!("\\x{byte:02x}")),
}
}
out.push('"');
out
}
fn encode_segment_into(segment: &[u8], out: &mut Vec<u8>) {
for byte in segment {
if *byte == 0 {
out.extend_from_slice(&[0x00, 0xff]);
} else {
out.push(*byte);
}
}
out.extend_from_slice(&[0x00, 0x00]);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn prefix_end_handles_empty_carry_and_unbounded_cases() {
assert_eq!(prefix_end(b""), None);
assert_eq!(prefix_end(b"abc"), Some(b"abd".to_vec()));
assert_eq!(prefix_end([0x12, 0xff]), Some(vec![0x13]));
assert_eq!(prefix_end([0xff, 0xff]), None);
}
#[test]
fn signed_and_unsigned_numeric_keys_sort_by_value() {
let mut signed = vec![i64::MAX, 0, -1, i64::MIN, 42, -42];
signed.sort_by_key(|value| i64_key(*value));
assert_eq!(signed, vec![i64::MIN, -42, -1, 0, 42, i64::MAX]);
let mut unsigned = vec![u64::MAX, 0, 9, 1, 1_000_000];
unsigned.sort_by_key(|value| u64_key(*value));
assert_eq!(unsigned, vec![0, 1, 9, 1_000_000, u64::MAX]);
}
#[test]
fn escaped_segments_round_trip_and_preserve_byte_order() {
let segments = vec![b"tenant".to_vec(), vec![0, 1, 0xff], Vec::new()];
let mut key = Vec::new();
for segment in &segments {
key.extend(encode_segment(segment));
}
assert_eq!(decode_segments(&key).unwrap(), segments);
let mut ordered = [
KeyBuilder::new().push_segment(b"a\0").finish(),
KeyBuilder::new().push_segment(b"").finish(),
KeyBuilder::new().push_segment(b"a").finish(),
KeyBuilder::new().push_segment(b"aa").finish(),
];
ordered.sort();
let decoded = ordered
.iter()
.map(|key| decode_segments(key).unwrap().remove(0))
.collect::<Vec<_>>();
assert_eq!(
decoded,
vec![b"".to_vec(), b"a".to_vec(), b"a\0".to_vec(), b"aa".to_vec()]
);
}
#[test]
fn decode_segments_rejects_partial_segments_and_bad_escapes() {
assert_eq!(
decode_segments(b"abc"),
Err(KeyDecodeError::UnexpectedEnd { offset: 3 })
);
assert_eq!(
decode_segments(&[0, 7]),
Err(KeyDecodeError::InvalidEscape {
offset: 0,
marker: 7
})
);
}
#[test]
fn debug_key_escapes_non_printable_bytes() {
assert_eq!(debug_key(b"a\n\0\\\""), "\"a\\n\\x00\\\\\\\"\"");
}
}