libreda_db/
index.rs

1// Copyright (c) 2020-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer
3//
4// SPDX-License-Identifier: AGPL-3.0-or-later
5
6//! Data structure for creating indices related to some other type. This is used to create
7//! handles for data stored in hash maps.
8
9use num_traits::{One, PrimInt, Zero};
10use std::cmp::Ordering;
11use std::fmt;
12use std::fmt::Formatter;
13use std::hash::{Hash, Hasher};
14use std::marker::PhantomData;
15
16/// An identifier for an arbitrary type `T`.
17/// This is a wrapper around `usize` which is bound to a type `T`.
18#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
19pub struct Index<T, Int = u32> {
20    index: Int,
21    phantom: PhantomData<T>,
22}
23
24impl<T, Int> fmt::Debug for Index<T, Int>
25where
26    Int: std::fmt::Display,
27{
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        write!(f, "Index({})", self.index)
30    }
31}
32
33impl<T, Int: Hash> Hash for Index<T, Int> {
34    fn hash<H: Hasher>(&self, state: &mut H) {
35        self.index.hash(state)
36    }
37}
38
39impl<T, Int: Copy> Copy for Index<T, Int> {}
40
41impl<T, Int: Copy> Clone for Index<T, Int> {
42    fn clone(&self) -> Self {
43        *self
44    }
45}
46
47impl<T, Int: PartialEq> Eq for Index<T, Int> {}
48
49impl<T, Int: PartialEq> PartialEq for Index<T, Int> {
50    fn eq(&self, other: &Self) -> bool {
51        self.index.eq(&other.index)
52    }
53}
54
55impl<T, Int: PartialOrd + Ord> Ord for Index<T, Int> {
56    fn cmp(&self, other: &Self) -> Ordering {
57        self.index.cmp(&other.index)
58    }
59}
60
61impl<T, Int: PartialOrd> PartialOrd for Index<T, Int> {
62    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
63        self.index.partial_cmp(&other.index)
64    }
65}
66
67impl<T, Int: fmt::Display> fmt::Display for Index<T, Int> {
68    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
69        write!(f, "{}", self.index)
70    }
71}
72
73impl<T, Int: Copy> Index<T, Int> {
74    pub(crate) fn new(index: Int) -> Self {
75        Index {
76            index,
77            phantom: Default::default(),
78        }
79    }
80
81    /// Get the integer value of this index.
82    pub fn value(&self) -> Int {
83        self.index
84    }
85}
86
87/// Generator for incrementing `Index<T>` values.
88#[derive(Debug, Clone)]
89#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
90pub(crate) struct IndexGenerator<T, Int = u32> {
91    counter: Int,
92    phantom: PhantomData<T>,
93}
94
95impl<T, Int: PrimInt + Zero + One> Default for IndexGenerator<T, Int> {
96    fn default() -> Self {
97        Self::new(Int::zero())
98    }
99}
100
101impl<T, Int: PrimInt + One> IndexGenerator<T, Int> {
102    /// Create a new index generator.
103    pub fn new(start: Int) -> Self {
104        IndexGenerator {
105            counter: start,
106            phantom: Default::default(),
107        }
108    }
109
110    // /// Jump forward with the counter.
111    // /// # Panics
112    // /// Panics when setting the counter to a smaller value.
113    // pub fn set_counter(&mut self, value: usize) {
114    //     assert!(value >= self.counter, "Cannot set the counter to a previous value.");
115    //     self.counter = value;
116    // }
117
118    /// Generate a new index.
119    pub fn next(&mut self) -> Index<T, Int> {
120        let index = Index::new(self.counter);
121        self.counter = self.counter + Int::one();
122        index
123    }
124}