intid_allocator/
lib.rs

1//! Allocates integer ids which implement [`intid::IntegerIdCounter`].
2//!
3//! Use [`IdAllocator`] if you want to be able to [free](IdAllocator::free) existing ids for reuse.
4//! This will minimize the integer value of the keys, reducing memory needed for lookup tables.
5//!
6//! Use [`UniqueIdAllocator`] or [`UniqueIdAllocatorAtomic`] if you don't care about reusing existing keys.
7//! These are more efficient and never require any allocation.
8#![cfg_attr(not(feature = "std"), no_std)]
9#![deny(unsafe_code)] // not needed yet
10
11#[cfg(feature = "alloc")]
12extern crate alloc;
13
14use core::fmt::{Debug, Display, Formatter};
15use core::marker::PhantomData;
16use intid::IntegerId;
17
18#[cfg(feature = "alloc")]
19mod reusing;
20mod unique;
21
22#[cfg(feature = "alloc")]
23pub use self::reusing::IdAllocator;
24#[cfg(feature = "atomic")]
25pub use self::unique::atomic::UniqueIdAllocatorAtomic;
26pub use self::unique::UniqueIdAllocator;
27
28/// Indicates that available ids have been exhausted,
29/// and can no longer be allocated.
30#[derive(Clone)]
31pub struct IdExhaustedError<T: IntegerId> {
32    marker: PhantomData<T>,
33}
34impl<T: IntegerId> IdExhaustedError<T> {
35    /// Indicate that ids have been exhausted for the type `T`,
36    /// without giving any additional information.
37    #[inline]
38    #[cold]
39    #[allow(clippy::new_without_default)] // doesn't make much sense for an error
40    #[must_use]
41    pub fn new() -> Self {
42        IdExhaustedError {
43            marker: PhantomData,
44        }
45    }
46
47    /// Trigger a descriptive panic due to this error.
48    ///
49    /// This gives a better panic message than calling [`Result::unwrap`].
50    ///
51    /// # Panics
52    /// Always.
53    #[track_caller]
54    #[cold]
55    pub fn panic(self) -> ! {
56        panic!("{self}")
57    }
58}
59impl<T: IntegerId> Display for IdExhaustedError<T> {
60    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
61        write!(f, "Ran out of ids for {}", core::any::type_name::<T>())
62    }
63}
64impl<T: IntegerId> Debug for IdExhaustedError<T> {
65    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
66        f.debug_struct("IdExhaustedError")
67            .field("type_name", &core::any::type_name::<T>())
68            .finish_non_exhaustive()
69    }
70}
71
72#[rustversion::since(1.81)]
73impl<T: IntegerId> core::error::Error for IdExhaustedError<T> {}
74
75#[rustversion::before(1.81)]
76#[cfg(feature = "std")]
77impl<T: IntegerId> std::error::Error for IdExhaustedError<T> {}