scsys_core/id/
identifier.rs

1/*
2    Appellation: atomic <mod>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5/// A generic identifier
6#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
7#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
8#[repr(transparent)]
9pub struct Id<T = usize>(pub T);
10
11impl<T> Id<T> {
12    /// Create a new identifier with the default value
13    pub fn new() -> Self
14    where
15        T: Default,
16    {
17        Self(T::default())
18    }
19    /// create a new identifier from the given value
20    pub fn from_value(id: T) -> Self {
21        Self(id)
22    }
23    #[cfg(feature = "rand")]
24    pub fn random() -> Self
25    where
26        rand_distr::StandardUniform: rand_distr::Distribution<T>,
27    {
28        use rand::Rng;
29        let mut rng = rand::rng();
30        Self::from_value(rng.random())
31    }
32    /// returns an immutable reference to the inner value
33    pub const fn get(&self) -> &T {
34        &self.0
35    }
36    /// returns a mutable reference to the inner value
37    pub fn get_mut(&mut self) -> &mut T {
38        &mut self.0
39    }
40    /// consumes the current instance to return the inner value
41    pub fn into_inner(self) -> T {
42        self.0
43    }
44    /// use the [`replace`](core::mem::replace) method to update and return the inner value
45    pub fn replace(&mut self, id: T) -> T {
46        core::mem::replace(self.get_mut(), id)
47    }
48    /// mutate the inner value and return a mutable reference to the wrapper for chaining
49    pub fn set(&mut self, id: T) -> &mut Self {
50        *self.get_mut() = id;
51        self
52    }
53    /// takes the inner value and replaces it with the default value
54    pub fn take(&mut self) -> T
55    where
56        T: Default,
57    {
58        core::mem::take(self.get_mut())
59    }
60    /// consumes the current instance to replace it with another.
61    pub fn with<U>(self, id: U) -> Id<U> {
62        Id(id)
63    }
64    /// apply a function onto the inner value and return a new instance with the result
65    pub fn map<U, F>(self, f: F) -> Id<U>
66    where
67        F: FnOnce(T) -> U,
68    {
69        Id(f(self.0))
70    }
71}
72
73impl Id<usize> {
74    pub fn atomic() -> Self {
75        use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
76        static COUNTER: AtomicUsize = AtomicUsize::new(1);
77        Self(COUNTER.fetch_add(1, Relaxed))
78    }
79
80    pub fn next(&self) -> Self {
81        Self::atomic()
82    }
83}
84
85#[cfg(feature = "uuid")]
86impl Id<uuid::Uuid> {
87    pub fn v3(namespace: &uuid::Uuid, name: &[u8]) -> Self {
88        let id = uuid::Uuid::new_v3(&namespace, name);
89        Self(id)
90    }
91
92    #[cfg(all(feature = "rng", feature = "uuid"))]
93    pub fn v4() -> Self {
94        let id = uuid::Uuid::new_v4();
95        Self(id)
96    }
97}
98
99impl<T> crate::id::Identifier for Id<T> {
100    seal!();
101}
102
103impl<T: Default> Default for Id<T> {
104    fn default() -> Self {
105        Self::new()
106    }
107}
108
109impl<T> AsRef<T> for Id<T> {
110    fn as_ref(&self) -> &T {
111        &self.0
112    }
113}
114
115impl<T> AsMut<T> for Id<T> {
116    fn as_mut(&mut self) -> &mut T {
117        &mut self.0
118    }
119}
120
121impl<T> core::borrow::Borrow<T> for Id<T> {
122    fn borrow(&self) -> &T {
123        &self.0
124    }
125}
126
127impl<T> core::borrow::BorrowMut<T> for Id<T> {
128    fn borrow_mut(&mut self) -> &mut T {
129        &mut self.0
130    }
131}
132
133impl<T> core::ops::Deref for Id<T> {
134    type Target = T;
135
136    fn deref(&self) -> &Self::Target {
137        &self.0
138    }
139}
140
141impl<T> core::ops::DerefMut for Id<T> {
142    fn deref_mut(&mut self) -> &mut Self::Target {
143        &mut self.0
144    }
145}
146
147macro_rules! fmt_atomic {
148    ($s:ident {$($trait:ident($($fmt:tt)*)),* $(,)?}) => {
149        $(
150            fmt_atomic!(@impl $s::$trait($($fmt)*));
151        )*
152    };
153    (@impl $s:ident::$trait:ident($($fmt:tt)*)) => {
154        impl<T> ::core::fmt::$trait for Id<T>
155        where
156            T: ::core::fmt::$trait
157        {
158            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
159                write!(f, $($fmt)*, self.0)
160            }
161        }
162    };
163}
164
165fmt_atomic! {
166    Id {
167        Binary("{:b}"),
168        Debug("{:?}"),
169        Display("{}"),
170        LowerExp("{:e}"),
171        LowerHex("{:x}"),
172        Octal("{:o}"),
173        UpperExp("{:E}"),
174        UpperHex("{:X}")
175    }
176}
177
178impl<S> PartialEq<S> for Id
179where
180    usize: PartialEq<S>,
181{
182    fn eq(&self, other: &S) -> bool {
183        self.0.eq(other)
184    }
185}