use moqtap_codec::varint::VarInt;
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
pub enum RequestIdError {
#[error("request ID {0} exceeds max {1}")]
ExceedsMax(u64, u64),
#[error("max request ID can only increase: was {0}, got {1}")]
Decreased(u64, u64),
#[error("no request IDs available (blocked)")]
Blocked,
}
pub struct RequestIdAllocator {
next_id: u64,
max_id: u64,
}
impl Default for RequestIdAllocator {
fn default() -> Self {
Self::new()
}
}
impl RequestIdAllocator {
pub fn new() -> Self {
Self { next_id: 0, max_id: 0 }
}
pub fn allocate(&mut self) -> Result<VarInt, RequestIdError> {
if self.max_id == 0 || self.next_id >= self.max_id {
return Err(RequestIdError::Blocked);
}
let id = VarInt::from_u64(self.next_id).unwrap();
self.next_id += 1;
Ok(id)
}
pub fn update_max(&mut self, new_max: u64) -> Result<(), RequestIdError> {
if new_max <= self.max_id {
return Err(RequestIdError::Decreased(self.max_id, new_max));
}
self.max_id = new_max;
Ok(())
}
pub fn validate_peer_id(&self, id: u64) -> Result<(), RequestIdError> {
if id >= self.max_id {
return Err(RequestIdError::ExceedsMax(id, self.max_id));
}
Ok(())
}
pub fn is_blocked(&self) -> bool {
self.max_id == 0 || self.next_id >= self.max_id
}
pub fn max_id(&self) -> u64 {
self.max_id
}
}