use std::collections::HashMap;
#[derive(Debug)]
pub struct HandleAllocator {
handle_max: u32,
next: u64,
free: Vec<u32>,
}
impl HandleAllocator {
pub fn new(handle_max: u32) -> Self {
HandleAllocator {
handle_max,
next: 0,
free: Vec::new(),
}
}
pub fn allocate(&mut self) -> Option<u32> {
if let Some(h) = self.free.pop() {
return Some(h);
}
if self.next <= self.handle_max as u64 {
let h = self.next as u32;
self.next += 1;
Some(h)
} else {
None
}
}
pub fn release(&mut self, handle: u32) {
self.free.push(handle);
}
}
#[derive(Debug, Default)]
pub struct RemoteHandleMap {
map: HashMap<u32, u32>,
}
impl RemoteHandleMap {
pub fn bind(&mut self, remote: u32, local: u32) {
self.map.insert(remote, local);
}
pub fn resolve(&self, remote: u32) -> Option<u32> {
self.map.get(&remote).copied()
}
pub fn unbind(&mut self, remote: u32) {
self.map.remove(&remote);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn allocates_and_releases() {
let mut a = HandleAllocator::new(1);
assert_eq!(a.allocate(), Some(0));
assert_eq!(a.allocate(), Some(1));
assert_eq!(a.allocate(), None);
a.release(0);
assert_eq!(a.allocate(), Some(0));
}
#[test]
fn remote_handle_routing() {
let mut m = RemoteHandleMap::default();
m.bind(9, 0);
assert_eq!(m.resolve(9), Some(0));
m.unbind(9);
assert_eq!(m.resolve(9), None);
}
}