/// intentionally does not implement copy or clone /// which should make it harder to misuse; /// the idea is to generally try to guarantee all IDs /// point to something valid, although duplicate /// gets around this if needed #[derive(Eq, Hash, PartialEq, Debug)] pub struct ID(usize); #[derive(Default)] pub struct IDTracker { free: Vec, cur: usize, } impl IDTracker { pub fn new() -> Self { Self::default() } #[allow(clippy::should_implement_trait)] pub fn next(&mut self) -> ID { if let Some(id) = self.free.pop() { return id; } let id = ID(self.cur); self.cur += 1; id } pub fn free(&mut self, id: ID) { self.free.push(id); } } impl ID { /// this must be used carefully to make sure /// all IDs are still valid references; /// named weirdly to indicate this. /// generally should not be used in "user" code pub fn duplicate(&self) -> Self { Self(self.0) } }