use std::collections::HashMap;
use std::sync::Mutex;
use crate::StorageError;
#[derive(Debug, Default)]
pub struct IdAllocator {
next: Mutex<HashMap<Vec<u8>, u64>>,
}
impl IdAllocator {
pub fn reserve(&self, key: &[u8], watermark: u64) -> Result<u64, StorageError> {
let mut next = self
.next
.lock()
.map_err(|_| StorageError::Builder("id allocator lock poisoned".into()))?;
let slot = next.entry(key.to_vec()).or_insert(0);
let id = (*slot).max(watermark);
*slot = id
.checked_add(1)
.ok_or_else(|| StorageError::ResourceExhausted("id counter exhausted".into()))?;
Ok(id)
}
}
#[cfg(test)]
mod tests {
use super::IdAllocator;
#[test]
fn reservations_are_unique_and_follow_the_watermark() {
let ids = IdAllocator::default();
assert_eq!(ids.reserve(b"c", 5).unwrap(), 5);
assert_eq!(ids.reserve(b"c", 5).unwrap(), 6);
assert_eq!(ids.reserve(b"c", 10).unwrap(), 10);
assert_eq!(ids.reserve(b"c", 0).unwrap(), 11);
assert_eq!(ids.reserve(b"d", 0).unwrap(), 0);
}
}