pub trait VecExt {
fn strip_key_prefix(&mut self, prefix: &[u8]);
fn prefix_with(&mut self, prefix: &[u8]);
fn prefix_range_end_with(&mut self, prefix: &[u8]);
}
impl VecExt for Vec<u8> {
fn strip_key_prefix(&mut self, prefix: &[u8]) {
if prefix.is_empty() {
return;
}
if !self.starts_with(prefix) {
return;
}
let pfx_len = prefix.len();
let key_len = self.len();
let new_len = key_len - pfx_len;
unsafe {
let ptr = self.as_mut_ptr();
std::ptr::copy(ptr.add(pfx_len), ptr, new_len);
self.set_len(new_len);
}
}
fn prefix_with(&mut self, prefix: &[u8]) {
if prefix.is_empty() {
return;
}
let pfx_len = prefix.len();
let key_len = self.len();
self.reserve(pfx_len);
unsafe {
let ptr = self.as_mut_ptr();
std::ptr::copy(ptr, ptr.add(pfx_len), key_len);
std::ptr::copy_nonoverlapping(prefix.as_ptr(), ptr, pfx_len);
self.set_len(key_len + pfx_len);
}
}
fn prefix_range_end_with(&mut self, prefix: &[u8]) {
if prefix.is_empty() {
return;
}
if self.len() == 1 && self[0] == 0 {
self.clear();
self.extend_from_slice(prefix);
let mut ok = false;
for i in (0..self.len()).rev() {
self[i] = self[i].wrapping_add(1);
if self[i] != 0 {
ok = true;
break;
}
}
if !ok {
self.clear();
self.push(0);
}
} else if !self.is_empty() {
self.prefix_with(prefix);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prefix_with() {
fn assert_prefix_with(pfx: &[u8], key: &[u8], end: &[u8], w_key: &[u8], w_end: &[u8]) {
let mut key = key.to_vec();
let mut end = end.to_vec();
key.prefix_with(pfx);
end.prefix_range_end_with(pfx);
assert_eq!(key, w_key);
assert_eq!(end, w_end);
}
assert_prefix_with(b"pfx/", b"a", b"", b"pfx/a", b"");
assert_prefix_with(b"pfx/", b"abc", b"def", b"pfx/abc", b"pfx/def");
assert_prefix_with(b"pfx/", b"abc", b"\0", b"pfx/abc", b"pfx0");
assert_prefix_with(b"\xFF\xFF", b"abc", b"\0", b"\xff\xffabc", b"\0");
}
}