charon_lib/ids/
generator.rs

1use index_vec::Idx;
2use std::marker::PhantomData;
3
4#[derive(Debug, Clone, Copy)]
5pub struct Generator<I: Idx> {
6    counter: usize,
7    phantom: PhantomData<I>,
8}
9
10impl<I: Idx> Generator<I> {
11    pub fn new() -> Self {
12        Self::new_with_init_value(I::from_usize(0))
13    }
14
15    pub fn new_with_init_value(index: I) -> Self {
16        Generator {
17            counter: index.index(),
18            phantom: PhantomData,
19        }
20    }
21
22    /// Get a fresh id from this generator.
23    pub fn fresh_id(&mut self) -> I {
24        let index = self.next_id();
25        self.advance(1);
26        index
27    }
28
29    /// Get the next id that would be emitted by `fresh_id`.
30    pub fn next_id(&self) -> I {
31        I::from_usize(self.counter)
32    }
33
34    /// Move the generator forward by the given delta.
35    pub fn advance(&mut self, by: usize) {
36        // The release version of the code doesn't check for overflows.
37        // As the max usize is very large, overflows are extremely
38        // unlikely. Still, it is extremely important for our code that
39        // no overflows happen on the index counters.
40        self.counter = self.counter.checked_add(by).unwrap();
41    }
42}
43
44// Manual impl to avoid the `I: Default` bound.
45impl<I: Idx> Default for Generator<I> {
46    fn default() -> Self {
47        Self {
48            counter: Default::default(),
49            phantom: Default::default(),
50        }
51    }
52}