use std::collections::HashMap;
#[derive(Debug)]
pub struct ChannelAllocator {
channel_max: u16,
next: u32,
free: Vec<u16>,
}
impl ChannelAllocator {
pub fn new(channel_max: u16) -> Self {
ChannelAllocator {
channel_max,
next: 0,
free: Vec::new(),
}
}
pub fn allocate(&mut self) -> Option<u16> {
if let Some(ch) = self.free.pop() {
return Some(ch);
}
if self.next <= self.channel_max as u32 {
let ch = self.next as u16;
self.next += 1;
Some(ch)
} else {
None
}
}
pub fn release(&mut self, channel: u16) {
self.free.push(channel);
}
pub fn in_use(&self) -> usize {
(self.next as usize).saturating_sub(self.free.len())
}
}
#[derive(Debug, Default)]
pub struct RemoteChannelMap {
map: HashMap<u16, u16>,
}
impl RemoteChannelMap {
pub fn bind(&mut self, remote: u16, local: u16) {
self.map.insert(remote, local);
}
pub fn resolve(&self, remote: u16) -> Option<u16> {
self.map.get(&remote).copied()
}
pub fn unbind(&mut self, remote: u16) {
self.map.remove(&remote);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn allocates_and_reuses_lowest() {
let mut a = ChannelAllocator::new(2);
assert_eq!(a.allocate(), Some(0));
assert_eq!(a.allocate(), Some(1));
assert_eq!(a.allocate(), Some(2));
assert_eq!(a.allocate(), None); a.release(1);
assert_eq!(a.allocate(), Some(1));
assert_eq!(a.in_use(), 3);
}
#[test]
fn remote_channel_routing() {
let mut m = RemoteChannelMap::default();
m.bind(7, 0);
assert_eq!(m.resolve(7), Some(0));
m.unbind(7);
assert_eq!(m.resolve(7), None);
}
}