pub fn encode_id_list(ids: &[u64]) -> Vec<u8> {
let mut buf = Vec::with_capacity(ids.len() * 2);
let mut prev = 0u64;
for &id in ids {
debug_assert!(id >= prev, "IDs must be sorted");
let delta = id - prev;
encode_varint(delta, &mut buf);
prev = id;
}
buf
}
pub fn decode_id_list(data: &[u8]) -> Vec<u64> {
let mut ids = Vec::new();
let mut pos = 0;
let mut prev = 0u64;
while pos < data.len() {
match decode_varint(&data[pos..]) {
Some((delta, bytes_read)) => {
pos += bytes_read;
prev += delta;
ids.push(prev);
}
None => break, }
}
ids
}
fn encode_varint(mut value: u64, buf: &mut Vec<u8>) {
loop {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
if value != 0 {
byte |= 0x80;
}
buf.push(byte);
if value == 0 {
break;
}
}
}
fn decode_varint(data: &[u8]) -> Option<(u64, usize)> {
let mut value: u64 = 0;
let mut shift = 0;
for (i, &byte) in data.iter().enumerate() {
value |= ((byte & 0x7F) as u64) << shift;
if byte & 0x80 == 0 {
return Some((value, i + 1));
}
shift += 7;
}
None }
pub fn insert_into_sorted(ids: &mut Vec<u64>, id: u64) {
match ids.binary_search(&id) {
Ok(_) => {} Err(pos) => ids.insert(pos, id),
}
}
pub fn remove_from_sorted(ids: &mut Vec<u64>, id: u64) -> bool {
match ids.binary_search(&id) {
Ok(pos) => {
ids.remove(pos);
true
}
Err(_) => false,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn roundtrip_empty() {
let ids: Vec<u64> = vec![];
let encoded = encode_id_list(&ids);
assert!(encoded.is_empty());
assert_eq!(decode_id_list(&encoded), ids);
}
#[test]
fn roundtrip_single() {
let ids = vec![42];
let encoded = encode_id_list(&ids);
assert_eq!(decode_id_list(&encoded), ids);
}
#[test]
fn roundtrip_sequential() {
let ids: Vec<u64> = (1..=1000).collect();
let encoded = encode_id_list(&ids);
assert_eq!(encoded.len(), 1000);
assert_eq!(decode_id_list(&encoded), ids);
}
#[test]
fn roundtrip_sparse() {
let ids = vec![100, 10_000, 1_000_000, u64::MAX / 2];
let encoded = encode_id_list(&ids);
assert_eq!(decode_id_list(&encoded), ids);
}
#[test]
fn insert_and_remove() {
let mut ids = vec![1, 3, 5, 7];
insert_into_sorted(&mut ids, 4);
assert_eq!(ids, vec![1, 3, 4, 5, 7]);
insert_into_sorted(&mut ids, 4); assert_eq!(ids, vec![1, 3, 4, 5, 7]);
assert!(remove_from_sorted(&mut ids, 4));
assert_eq!(ids, vec![1, 3, 5, 7]);
assert!(!remove_from_sorted(&mut ids, 4)); }
}