1use hibitset::BitSet;
19use serde::{Serialize, Serializer};
20use std::borrow::Borrow;
21use std::fmt;
22use std::hash::Hash;
23use std::marker::PhantomData;
24use std::ops::{AddAssign, Sub};
25use std::sync::atomic::{AtomicU64, Ordering};
26use std::sync::{Arc, Mutex};
27use uuid::Uuid;
28
29use rand::RngExt;
30use rand::rngs::StdRng;
31
32use crate::cast::CastFrom;
33
34#[derive(Debug, Clone)]
36pub struct Gen<Id> {
37 id: u64,
38 phantom: PhantomData<Id>,
39}
40
41impl<Id> Default for Gen<Id> {
42 fn default() -> Self {
43 Self {
44 id: 0,
45 phantom: PhantomData,
46 }
47 }
48}
49
50impl<Id: From<u64>> Gen<Id> {
51 pub fn allocate_id(&mut self) -> Id {
53 let id = self.id;
54 self.id += 1;
55 id.into()
56 }
57}
58
59pub type IdGen = Gen<u64>;
61
62#[derive(Debug)]
66pub struct AtomicGen<Id> {
67 id: AtomicU64,
68 phantom: PhantomData<Id>,
69}
70
71impl<Id> Default for AtomicGen<Id> {
72 fn default() -> Self {
73 Self {
74 id: AtomicU64::new(0),
75 phantom: PhantomData,
76 }
77 }
78}
79
80impl<Id: From<u64> + Default> AtomicGen<Id> {
81 pub fn allocate_id(&self) -> Id {
83 let id = self.id.fetch_add(1, Ordering::Relaxed);
87 id.into()
88 }
89}
90
91pub type AtomicIdGen = AtomicGen<u64>;
95
96pub trait IdGenerator:
98 From<u8> + AddAssign + Sub + PartialOrd + Copy + Eq + Hash + Ord + Serialize + fmt::Display
99{
100}
101
102impl<T> IdGenerator for T where
103 T: From<u8> + AddAssign + Sub + PartialOrd + Copy + Eq + Hash + Ord + Serialize + fmt::Display
104{
105}
106
107#[derive(Debug)]
109pub struct IdAllocator<A: IdAllocatorInner>(pub Arc<Mutex<A>>);
110
111impl<A: IdAllocatorInner> Clone for IdAllocator<A> {
113 fn clone(&self) -> Self {
114 IdAllocator(Arc::clone(&self.0))
115 }
116}
117
118pub trait IdAllocatorInner: std::fmt::Debug + Send {
120 const NAME: &'static str;
122 fn new(min: u32, max: u32, mask: u32) -> Self;
125 fn alloc(&mut self) -> Option<u32>;
127 fn remove(&mut self, id: u32);
129}
130
131#[derive(Debug)]
133pub struct IdAllocatorInnerBitSet {
134 next: StdRng,
135 min: u32,
136 max: u32,
137 mask: u32,
138 used: BitSet,
139}
140
141impl IdAllocatorInner for IdAllocatorInnerBitSet {
142 const NAME: &'static str = "hibitset";
143
144 fn new(min: u32, max: u32, mask: u32) -> Self {
145 let total = usize::cast_from(max - min);
146 assert!(total < BitSet::BITS_PER_USIZE.pow(4));
147 IdAllocatorInnerBitSet {
148 next: rand::make_rng(),
149 min,
150 max,
151 mask,
152 used: BitSet::new(),
153 }
154 }
155
156 fn alloc(&mut self) -> Option<u32> {
157 let range = self.min..=self.max;
158 let init = self.next.random_range(range);
159 let mut next = init;
160 loop {
161 let stored = next - self.min;
165 if !self.used.add(stored) {
166 assert!(
167 next & self.mask == 0,
168 "chosen ID must not intersect with mask:\n{:#034b}\n{:#034b}",
169 next,
170 self.mask
171 );
172 return Some(next | self.mask);
173 }
174 next = if next == self.max { self.min } else { next + 1 };
176 if next == init {
179 return None;
180 }
181 }
182 }
183
184 fn remove(&mut self, id: u32) {
185 let id = (!self.mask) & id;
186 let stored = id - self.min;
187 self.used.remove(stored);
188 }
189}
190
191impl<A: IdAllocatorInner> IdAllocator<A> {
192 pub fn new(min: u32, max: u32, mask: u32) -> IdAllocator<A> {
195 assert!(min <= max);
196 if mask != 0 && max > 0 {
197 let mask_check = (1 << (max.ilog2() + 1)) - 1;
200 assert_eq!(mask & mask_check, 0, "max and mask share bits");
201 }
202 let inner = A::new(min, max, mask);
203 IdAllocator(Arc::new(Mutex::new(inner)))
204 }
205
206 pub fn alloc(&self) -> Option<IdHandle<u32, A>> {
213 let inner = Arc::new(internal::IdHandleInner::new(self)?);
214 Some(IdHandle::Dynamic(inner))
215 }
216
217 fn alloc_internal(&self) -> Option<u32> {
225 let mut inner = self.0.lock().expect("lock poisoned");
226 inner.alloc()
227 }
228
229 fn free_internal(&self, id: u32) {
230 let mut inner = self.0.lock().expect("lock poisoned");
231 inner.remove(id);
232 }
233}
234
235#[derive(Debug)]
240pub enum IdHandle<T, A: IdAllocatorInner> {
241 Static(T),
246 Dynamic(Arc<internal::IdHandleInner<T, A>>),
248}
249
250impl<T: Clone, A: IdAllocatorInner> Clone for IdHandle<T, A> {
251 fn clone(&self) -> Self {
252 match self {
253 IdHandle::Static(t) => IdHandle::Static(t.clone()),
254 IdHandle::Dynamic(handle) => IdHandle::Dynamic(Arc::clone(handle)),
255 }
256 }
257}
258
259impl<T: IdGenerator, A: IdAllocatorInner> IdHandle<T, A> {
260 pub fn unhandled(&self) -> T {
266 *self.borrow()
267 }
268}
269
270impl<T: IdGenerator, A: IdAllocatorInner> PartialEq for IdHandle<T, A> {
271 fn eq(&self, other: &Self) -> bool {
272 self.unhandled() == other.unhandled()
273 }
274}
275impl<T: IdGenerator, A: IdAllocatorInner> Eq for IdHandle<T, A> {}
276
277impl<T: IdGenerator, A: IdAllocatorInner> PartialOrd for IdHandle<T, A> {
278 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
279 Some(self.cmp(other))
280 }
281}
282
283impl<T: IdGenerator, A: IdAllocatorInner> Ord for IdHandle<T, A> {
284 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
285 self.unhandled().cmp(&other.unhandled())
286 }
287}
288
289impl<T, A: IdAllocatorInner> Borrow<T> for IdHandle<T, A> {
290 fn borrow(&self) -> &T {
291 match self {
292 IdHandle::Static(id) => id,
293 IdHandle::Dynamic(inner) => &inner.id,
294 }
295 }
296}
297
298impl<T: IdGenerator, A: IdAllocatorInner> fmt::Display for IdHandle<T, A> {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 self.unhandled().fmt(f)
301 }
302}
303
304impl<T: IdGenerator, A: IdAllocatorInner> Serialize for IdHandle<T, A> {
305 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
306 where
307 S: Serializer,
308 {
309 self.unhandled().serialize(serializer)
310 }
311}
312
313mod internal {
314 use std::fmt::Debug;
315 use std::sync::Arc;
316
317 use crate::cast::CastFrom;
318 use crate::id_gen::{IdAllocator, IdAllocatorInner};
319
320 pub struct IdHandleInner<T, A: IdAllocatorInner> {
321 pub(super) allocator: IdAllocator<A>,
323 pub(super) id: T,
325 stored: u32,
326 }
327
328 impl<T: Debug, A: IdAllocatorInner> Debug for IdHandleInner<T, A> {
329 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
330 f.debug_struct("IdHandleInner")
331 .field("id", &self.id)
332 .field("stored", &self.stored)
333 .finish_non_exhaustive()
334 }
335 }
336
337 impl<T, A: IdAllocatorInner> IdHandleInner<T, A>
338 where
339 T: CastFrom<u32>,
340 {
341 pub fn new(allocator: &IdAllocator<A>) -> Option<Self> {
342 let stored = allocator.alloc_internal()?;
343 Some(IdHandleInner {
344 allocator: IdAllocator(Arc::clone(&allocator.0)),
345 id: T::cast_from(stored),
346 stored,
347 })
348 }
349 }
350
351 impl<T, A: IdAllocatorInner> Drop for IdHandleInner<T, A> {
352 fn drop(&mut self) {
353 self.allocator.free_internal(self.stored);
355 }
356 }
357}
358
359pub const ORG_ID_OFFSET: usize = 19;
361
362pub const MAX_ORG_ID: u32 = (1 << ORG_ID_OFFSET) - 1;
364
365pub fn org_id_conn_bits(uuid: &Uuid) -> u32 {
368 let lower = uuid.as_u128();
369 let lower = (lower & 0xFFF) << ORG_ID_OFFSET;
370 let lower: u32 = lower.try_into().expect("must fit");
371 lower
372}
373
374pub fn conn_id_org_uuid(conn_id: u32) -> String {
376 const UPPER: [char; 16] = [
377 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
378 ];
379
380 let orgid = usize::try_from((conn_id >> ORG_ID_OFFSET) & 0xFFF).expect("must cast");
382 let mut dst = String::with_capacity(3);
384 dst.push(UPPER[(orgid >> 8) & 0xf]);
385 dst.push(UPPER[(orgid >> 4) & 0xf]);
386 dst.push(UPPER[orgid & 0xf]);
387 dst
388}
389
390pub fn temp_id() -> String {
404 let temp_uuid = uuid::Uuid::new_v4().as_hyphenated().to_string();
405 temp_uuid.chars().rev().take_while(|c| *c != '-').collect()
406}
407
408#[cfg(test)]
409mod tests {
410 use std::collections::BTreeMap;
411
412 use crate::assert_none;
413
414 use super::*;
415
416 #[crate::test]
417 fn test_conn_org() {
418 let uuid = Uuid::parse_str("9e37ec59-56f4-450a-acbd-18ff14f10ca8").unwrap();
419 let lower = org_id_conn_bits(&uuid);
420 let org_lower_uuid = conn_id_org_uuid(lower);
421 assert_eq!(org_lower_uuid, "CA8");
422 }
423
424 #[crate::test]
425 fn test_id_gen() {
426 test_ad_allocator::<IdAllocatorInnerBitSet>();
427 }
428
429 #[crate::test]
431 #[should_panic]
432 fn test_mask_intersect<A: IdAllocatorInner>() {
433 let env_lower = org_id_conn_bits(&uuid::Uuid::from_u128(u128::MAX));
434 let ida = IdAllocator::<IdAllocatorInnerBitSet>::new(
435 1 << ORG_ID_OFFSET,
436 1 << ORG_ID_OFFSET,
437 env_lower,
438 );
439 let id = ida.alloc().unwrap();
440 assert_eq!(id.unhandled(), (0xfff << ORG_ID_OFFSET) | MAX_ORG_ID);
441 }
442
443 fn test_ad_allocator<A: IdAllocatorInner>() {
444 test_id_alloc::<A>();
445 test_static_id_sorting::<A>();
446 test_id_reuse::<A>();
447 test_display::<A>();
448 test_map_lookup::<A>();
449 test_serialization::<A>();
450 test_mask::<A>();
451 test_mask_envd::<A>();
452 }
453
454 fn test_mask<A: IdAllocatorInner>() {
455 let ida = IdAllocator::<A>::new(1, 1, 0xfff << 20);
456 let id = ida.alloc().unwrap();
457 assert_eq!(id.unhandled(), (0xfff << 20) | 1);
458 }
459
460 fn test_mask_envd<A: IdAllocatorInner>() {
462 let env_lower = org_id_conn_bits(&uuid::Uuid::from_u128(u128::MAX));
463 let ida = IdAllocator::<A>::new(MAX_ORG_ID, MAX_ORG_ID, env_lower);
464 let id = ida.alloc().unwrap();
465 assert_eq!(id.unhandled(), (0xfff << ORG_ID_OFFSET) | MAX_ORG_ID);
466 }
467
468 fn test_id_alloc<A: IdAllocatorInner>() {
469 let ida = IdAllocator::<A>::new(3, 5, 0);
470 let id3 = ida.alloc().unwrap();
471 let id4 = ida.alloc().unwrap();
472 let id5 = ida.alloc().unwrap();
473 assert_ne!(id3, id4);
474 assert_ne!(id3, id5);
475 assert_ne!(id4, id5);
476 drop(id4);
477 let _id4 = ida.alloc().unwrap();
478 drop(id5);
479 drop(id3);
480 let _id5 = ida.alloc().unwrap();
481 let _id3 = ida.alloc().unwrap();
482 match ida.alloc() {
483 Some(id) => panic!(
484 "id allocator returned {}, not expected id exhaustion error",
485 id
486 ),
487 None => (),
488 }
489 }
490
491 fn test_static_id_sorting<A: IdAllocatorInner>() {
492 let ida = IdAllocator::<A>::new(0, 0, 0);
493 let id0 = ida.alloc().unwrap();
494 let id1 = IdHandle::Static(1);
495 assert!(id0 < id1);
496
497 let ida = IdAllocator::<A>::new(1, 1, 0);
498 let id0 = IdHandle::Static(0);
499 let id1 = ida.alloc().unwrap();
500 assert!(id0 < id1);
501 }
502
503 fn test_id_reuse<A: IdAllocatorInner>() {
504 let allocator = IdAllocator::<A>::new(10, 11, 0);
505
506 let id_a = allocator.alloc().unwrap();
507 let a = id_a.unhandled();
508 let id_a_clone = id_a.clone();
509 drop(id_a);
511
512 let _id_b = allocator.alloc().unwrap();
514 assert_none!(allocator.alloc());
515
516 drop(id_a_clone);
518
519 let id_c = allocator.alloc().unwrap();
521 assert_eq!(id_c.unhandled(), a);
522 }
523
524 fn test_display<A: IdAllocatorInner>() {
525 let allocator = IdAllocator::<A>::new(65_000, 65_000, 0);
526
527 let id_a = allocator.alloc().unwrap();
528 assert_eq!(id_a.unhandled(), 65_000);
529
530 let id_display = format!("{id_a}");
532 let val_display = format!("{}", id_a.unhandled());
533
534 assert_eq!(id_display, val_display);
535 }
536
537 fn test_map_lookup<A: IdAllocatorInner>() {
538 let allocator = IdAllocator::<A>::new(99, 101, 0);
539
540 let id_a = allocator.alloc().unwrap();
541 let a = id_a.unhandled();
542
543 let mut btree = BTreeMap::new();
544 btree.insert(id_a, "hello world");
545
546 let entry = btree.remove(&a).unwrap();
548 assert_eq!(entry, "hello world");
549
550 assert!(btree.is_empty());
551 }
552
553 fn test_serialization<A: IdAllocatorInner>() {
554 let allocator = IdAllocator::<A>::new(42, 42, 0);
555
556 let id_a = allocator.alloc().unwrap();
557 assert_eq!(id_a.unhandled(), 42);
558
559 let id_json = serde_json::to_string(&id_a).unwrap();
561 let val_json = serde_json::to_string(&id_a.unhandled()).unwrap();
562
563 assert_eq!(id_json, val_json);
564 }
565}