use kvproto::coprocessor as coppb;
pub fn convert_to_prefix_next(key: &mut Vec<u8>) {
if key.is_empty() {
key.push(0);
return;
}
let mut i = key.len() - 1;
loop {
if key[i] == 255 {
key[i] = 0;
} else {
key[i] += 1;
return;
}
if i == 0 {
for byte in key.iter_mut() {
*byte = 255;
}
key.push(0);
return;
}
i -= 1;
}
}
pub fn is_prefix_next(key: &[u8], next: &[u8]) -> bool {
let len = key.len();
let next_len = next.len();
if len == next_len {
let mut carry_pos = len;
loop {
if carry_pos == 0 {
return false;
}
carry_pos -= 1;
if key[carry_pos] != 255 {
break;
}
}
key[carry_pos] + 1 == next[carry_pos]
&& next[carry_pos + 1..].iter().all(|byte| *byte == 0)
&& key[..carry_pos] == next[..carry_pos]
} else if len + 1 == next_len {
*next.last().unwrap() == 0
&& key.iter().all(|byte| *byte == 255)
&& next.iter().take(len).all(|byte| *byte == 255)
} else {
false
}
}
#[inline]
pub fn is_point(range: &coppb::KeyRange) -> bool {
is_prefix_next(range.get_start(), range.get_end())
}
#[cfg(test)]
mod tests {
use super::*;
fn test_prefix_next_once(key: &[u8], expected: &[u8]) {
let mut key = key.to_vec();
convert_to_prefix_next(&mut key);
assert_eq!(key.as_slice(), expected);
}
#[test]
fn test_prefix_next() {
test_prefix_next_once(&[], &[0]);
test_prefix_next_once(&[0], &[1]);
test_prefix_next_once(&[1], &[2]);
test_prefix_next_once(&[255], &[255, 0]);
test_prefix_next_once(&[255, 255, 255], &[255, 255, 255, 0]);
test_prefix_next_once(&[1, 255], &[2, 0]);
test_prefix_next_once(&[0, 1, 255], &[0, 2, 0]);
test_prefix_next_once(&[0, 1, 255, 5], &[0, 1, 255, 6]);
test_prefix_next_once(&[0, 1, 5, 255], &[0, 1, 6, 0]);
test_prefix_next_once(&[0, 1, 255, 255], &[0, 2, 0, 0]);
test_prefix_next_once(&[0, 255, 255, 255], &[1, 0, 0, 0]);
}
fn test_is_prefix_next_case(lhs: &[u8], expected: &[u8], unexpected: &[&[u8]]) {
assert!(is_prefix_next(lhs, expected));
for rhs in unexpected {
assert!(!is_prefix_next(lhs, rhs));
}
}
#[test]
fn test_is_prefix_next() {
test_is_prefix_next_case(&[], &[0], &[&[], &[1], &[2]]);
test_is_prefix_next_case(&[0], &[1], &[&[], &[0], &[0, 0], &[2], &[255]]);
test_is_prefix_next_case(&[1], &[2], &[&[], &[1], &[3], &[1, 0]]);
test_is_prefix_next_case(&[255], &[255, 0], &[&[0], &[255, 255, 0]]);
test_is_prefix_next_case(
&[255, 255, 255],
&[255, 255, 255, 0],
&[
&[],
&[0],
&[0, 0, 0],
&[255, 255, 0],
&[255, 255, 255, 255, 0],
],
);
test_is_prefix_next_case(
&[1, 255],
&[2, 0],
&[&[], &[1, 255, 0], &[2, 255], &[1, 255], &[2, 0, 0]],
);
test_is_prefix_next_case(
&[0, 255],
&[1, 0],
&[&[], &[0, 255, 0], &[1, 255], &[0, 255], &[1, 0, 0]],
);
test_is_prefix_next_case(
&[1, 2, 3, 4, 255, 255],
&[1, 2, 3, 5, 0, 0],
&[
&[],
&[1, 2, 3, 4, 255, 255],
&[1, 2, 3, 4, 0, 0],
&[1, 2, 3, 5, 255, 255],
&[1, 2, 3, 5, 0, 1],
&[1, 2, 3, 5, 1, 0],
&[1, 2, 4, 0, 0, 0],
],
);
}
}