1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use parking_lot::Mutex; use std::{fmt, ops::AddAssign, sync::Arc}; #[derive(Clone)] pub(crate) struct IdSequence<T> { inner: Arc<Mutex<Inner<T>>>, } impl<T: Default + Copy + AddAssign<T> + PartialEq<T> + PartialOrd<T> + From<u8>> IdSequence<T> { pub(crate) fn new(allow_zero: bool) -> Self { Self { inner: Arc::new(Mutex::new(Inner::new(allow_zero))), } } pub(crate) fn next(&self) -> T { self.inner.lock().next() } pub(crate) fn set_max(&self, max: T) { self.inner.lock().set_max(max) } } impl<T: fmt::Debug> fmt::Debug for IdSequence<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut debug = f.debug_struct("IdSequence"); if let Some(inner) = self.inner.try_lock() { debug .field("allow_zero", &inner.allow_zero) .field("max", &inner.max) .field("id", &inner.id); } debug.finish() } } #[derive(Debug)] struct Inner<T> { allow_zero: bool, zero: T, one: T, max: Option<T>, id: T, } impl<T: Default + Copy + AddAssign<T> + PartialEq<T> + PartialOrd<T> + From<u8>> Inner<T> { fn new(allow_zero: bool) -> Self { Self { allow_zero, zero: 0.into(), one: 1.into(), max: None, id: T::default(), } } fn set_max(&mut self, max: T) { self.max = if max == self.zero { None } else { Some(max) }; } fn next(&mut self) -> T { if !self.allow_zero && self.id == self.zero { self.id += self.one; } if self.check_max() { let id = self.id; self.id += self.one; id } else { self.id = self.zero; self.next() } } fn check_max(&self) -> bool { if let Some(max) = self.max { self.id < max } else { true } } }