use alloc::collections::BinaryHeap;
use crate::{IdExhaustedError, UniqueIdAllocator};
use intid::IntegerIdCounter;
pub struct IdAllocator<T: IntegerIdCounter> {
next_id: crate::UniqueIdAllocator<T>,
heap: BinaryHeap<core::cmp::Reverse<intid::utils::OrderByInt<T>>>,
}
impl<T: IntegerIdCounter> Default for IdAllocator<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: IntegerIdCounter> IdAllocator<T> {
#[inline]
#[rustversion::attr(since(1.80), const)]
pub fn new() -> Self {
Self::with_start(T::START)
}
#[inline]
#[rustversion::attr(since(1.80), const)]
#[rustversion::attr(since(1.80), clippy::msrv = "1.80")]
pub fn with_start(start: T) -> Self {
IdAllocator {
next_id: UniqueIdAllocator::with_start(start),
heap: alloc::collections::BinaryHeap::new(),
}
}
#[inline]
pub fn try_alloc(&mut self) -> Result<T, IdExhaustedError<T>> {
match self.heap.pop() {
Some(existing) => Ok(existing.0 .0),
None => self.next_id.try_alloc(),
}
}
#[track_caller]
#[inline]
#[must_use]
pub fn alloc(&mut self) -> T {
match self.try_alloc() {
Ok(id) => id,
Err(e) => e.panic(),
}
}
#[inline]
pub fn free_all(&mut self) {
self.heap.clear();
self.next_id.reset();
}
#[inline]
pub fn free(&mut self, id: T) {
self.heap
.push(core::cmp::Reverse(intid::utils::OrderByInt(id)));
}
}