#[repr(C)] #[derive(Eq, Hash, PartialEq, Debug, Clone, Copy, bytemuck::Zeroable)] pub struct Id(I); unsafe impl bytemuck::Pod for Id {} pub struct IdTracker { free: Vec>, cur: Id, } impl IdTracker { #[allow(clippy::should_implement_trait)] pub fn next(&mut self) -> Id { if let Some(id) = self.free.pop() { return id; } let next = self.cur.next(); std::mem::replace(&mut self.cur, next) } #[allow(dead_code)] pub fn free(&mut self, id: Id) { self.free.push(id); } } impl Id { #[allow(dead_code)] /// for debug purposes; should this be exposed? /// generally you want to use labels with widgets pub(crate) fn raw(id: I) -> Self { Self(id) } pub fn idx(&self) -> usize { self.0.idx() } pub fn next(&self) -> Id { Self(self.0.next()) } pub const fn preset(value: I) -> Self { Self(value) } } impl Default for IdTracker { fn default() -> Self { Self { free: Vec::new(), cur: Id(I::first()), } } } pub trait IdNum { fn first() -> Self; fn next(&self) -> Self; fn idx(&self) -> usize; } impl IdNum for u64 { fn first() -> Self { 0 } fn next(&self) -> Self { self + 1 } fn idx(&self) -> usize { *self as usize } } impl IdNum for u32 { fn first() -> Self { 0 } fn next(&self) -> Self { self + 1 } fn idx(&self) -> usize { *self as usize } }