manifoldb_graph/store/
id_gen.rs1use std::sync::atomic::{AtomicU64, Ordering};
7
8use manifoldb_core::{EdgeId, EntityId};
9
10#[derive(Debug)]
31pub struct IdGenerator {
32 next_entity_id: AtomicU64,
34 next_edge_id: AtomicU64,
36}
37
38impl IdGenerator {
39 #[must_use]
41 pub const fn new() -> Self {
42 Self { next_entity_id: AtomicU64::new(1), next_edge_id: AtomicU64::new(1) }
43 }
44
45 #[must_use]
55 pub const fn with_start(entity_start: u64, edge_start: u64) -> Self {
56 Self {
57 next_entity_id: AtomicU64::new(entity_start),
58 next_edge_id: AtomicU64::new(edge_start),
59 }
60 }
61
62 pub fn next_entity_id(&self) -> EntityId {
66 let id = self.next_entity_id.fetch_add(1, Ordering::Relaxed);
67 EntityId::new(id)
68 }
69
70 pub fn next_edge_id(&self) -> EdgeId {
74 let id = self.next_edge_id.fetch_add(1, Ordering::Relaxed);
75 EdgeId::new(id)
76 }
77
78 #[must_use]
80 pub fn current_entity_counter(&self) -> u64 {
81 self.next_entity_id.load(Ordering::Relaxed)
82 }
83
84 #[must_use]
86 pub fn current_edge_counter(&self) -> u64 {
87 self.next_edge_id.load(Ordering::Relaxed)
88 }
89
90 pub fn reset_entity_counter(&self, value: u64) {
94 self.next_entity_id.store(value, Ordering::Relaxed);
95 }
96
97 pub fn reset_edge_counter(&self, value: u64) {
101 self.next_edge_id.store(value, Ordering::Relaxed);
102 }
103}
104
105impl Default for IdGenerator {
106 fn default() -> Self {
107 Self::new()
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn new_generator_starts_at_one() {
117 let gen = IdGenerator::new();
118 assert_eq!(gen.next_entity_id().as_u64(), 1);
119 assert_eq!(gen.next_edge_id().as_u64(), 1);
120 }
121
122 #[test]
123 fn ids_are_monotonically_increasing() {
124 let gen = IdGenerator::new();
125 let ids: Vec<_> = (0..100).map(|_| gen.next_entity_id().as_u64()).collect();
126 for window in ids.windows(2) {
127 assert!(window[0] < window[1]);
128 }
129 }
130
131 #[test]
132 fn with_start_sets_initial_values() {
133 let gen = IdGenerator::with_start(100, 200);
134 assert_eq!(gen.next_entity_id().as_u64(), 100);
135 assert_eq!(gen.next_edge_id().as_u64(), 200);
136 assert_eq!(gen.next_entity_id().as_u64(), 101);
137 assert_eq!(gen.next_edge_id().as_u64(), 201);
138 }
139
140 #[test]
141 fn current_counter_reflects_next_id() {
142 let gen = IdGenerator::new();
143 assert_eq!(gen.current_entity_counter(), 1);
144 gen.next_entity_id();
145 assert_eq!(gen.current_entity_counter(), 2);
146 }
147
148 #[test]
149 fn reset_counter_works() {
150 let gen = IdGenerator::new();
151 gen.next_entity_id();
152 gen.next_entity_id();
153 gen.reset_entity_counter(1000);
154 assert_eq!(gen.next_entity_id().as_u64(), 1000);
155 }
156
157 #[test]
158 fn entity_and_edge_ids_are_independent() {
159 let gen = IdGenerator::new();
160 assert_eq!(gen.next_entity_id().as_u64(), 1);
161 assert_eq!(gen.next_entity_id().as_u64(), 2);
162 assert_eq!(gen.next_edge_id().as_u64(), 1);
163 assert_eq!(gen.next_entity_id().as_u64(), 3);
164 assert_eq!(gen.next_edge_id().as_u64(), 2);
165 }
166}