use crate::IdExhaustedError;
use core::cell::Cell;
use intid::{uint, IntegerIdCounter};
#[cfg(feature = "atomic")]
pub mod atomic;
#[derive(Clone, Debug)]
pub struct UniqueIdAllocator<T: IntegerIdCounter> {
next_id: Cell<Option<T>>,
}
impl<T: IntegerIdCounter> Default for UniqueIdAllocator<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: IntegerIdCounter> UniqueIdAllocator<T> {
#[inline]
pub fn max_used_id(&self) -> Option<T> {
self.next_id
.get()
.and_then(|id| IntegerIdCounter::checked_sub(id, uint::one()))
}
#[inline]
pub const fn new() -> Self {
Self::with_start(T::START)
}
#[inline]
pub const fn with_start(start: T) -> Self {
UniqueIdAllocator {
next_id: Cell::new(Some(start)),
}
}
#[inline]
#[track_caller]
pub fn alloc(&self) -> T {
match self.try_alloc() {
Ok(id) => id,
Err(e) => e.panic(),
}
}
#[inline]
pub fn try_alloc(&self) -> Result<T, IdExhaustedError<T>> {
let old_id = self.next_id.get().ok_or_else(IdExhaustedError::new)?;
self.next_id
.set(IntegerIdCounter::checked_add(old_id, intid::uint::one()));
Ok(old_id)
}
#[inline]
pub fn set_next_id(&self, next_id: T) {
self.next_id.set(Some(next_id));
}
#[inline]
pub fn reset(&self) {
self.set_next_id(T::START);
}
}