1use std::{cmp::Ordering, fmt, num::NonZeroU128};
5
6use crate::{
7 error::{Error, ErrorKind},
8 Uuid,
9};
10
11#[repr(transparent)]
35#[derive(#[automatically_derived]impl ::core::marker::Copy for NonNilUuid { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for NonNilUuid {
}
#[automatically_derived]impl ::core::clone::Clone for NonNilUuid {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<NonZeroU128>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
NonNilUuid {
}
#[automatically_derived]impl ::core::cmp::PartialEq for NonNilUuid {
#[inline]
fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for NonNilUuid {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<NonZeroU128>;
}
}Eq, #[automatically_derived]impl ::core::hash::Hash for NonNilUuid {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, #[automatically_derived]impl ::core::cmp::PartialOrd for NonNilUuid {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for NonNilUuid {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
36pub struct NonNilUuid(NonZeroU128);
37
38impl fmt::Debug for NonNilUuid {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 fmt::Debug::fmt(&Uuid::from(*self), f)
41 }
42}
43
44impl fmt::Display for NonNilUuid {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 fmt::Display::fmt(&Uuid::from(*self), f)
47 }
48}
49
50impl PartialEq<Uuid> for NonNilUuid {
51 fn eq(&self, other: &Uuid) -> bool {
52 self.get() == *other
53 }
54}
55
56impl PartialEq<NonNilUuid> for Uuid {
57 fn eq(&self, other: &NonNilUuid) -> bool {
58 *self == other.get()
59 }
60}
61
62impl PartialOrd<Uuid> for NonNilUuid {
63 fn partial_cmp(&self, other: &Uuid) -> Option<Ordering> {
64 self.get().partial_cmp(other)
65 }
66}
67
68impl PartialOrd<NonNilUuid> for Uuid {
69 fn partial_cmp(&self, other: &NonNilUuid) -> Option<Ordering> {
70 self.partial_cmp(&other.get())
71 }
72}
73
74impl NonNilUuid {
75 pub const fn new(uuid: Uuid) -> Option<Self> {
77 match NonZeroU128::new(uuid.as_u128()) {
78 Some(non_nil) => Some(NonNilUuid(non_nil)),
79 None => None,
80 }
81 }
82
83 pub const unsafe fn new_unchecked(uuid: Uuid) -> Self {
89 NonNilUuid(unsafe { NonZeroU128::new_unchecked(uuid.as_u128()) })
90 }
91
92 #[inline]
94 pub const fn get(self) -> Uuid {
95 Uuid::from_u128(self.0.get())
96 }
97
98 #[cfg(feature = "v1")]
102 pub fn new_v1(ts: crate::Timestamp, node_id: &[u8; 6]) -> Self {
103 unsafe { Self::new_unchecked(Uuid::new_v1(ts, node_id)) }
105 }
106
107 #[cfg(all(feature = "v1", feature = "std", feature = "rng"))]
111 pub fn now_v1(node_id: &[u8; 6]) -> Self {
112 unsafe { Self::new_unchecked(Uuid::now_v1(node_id)) }
114 }
115
116 #[cfg(feature = "v3")]
120 pub fn new_v3(namespace: &Uuid, name: &[u8]) -> Self {
121 unsafe { Self::new_unchecked(Uuid::new_v3(namespace, name)) }
123 }
124
125 #[cfg(feature = "v4")]
129 pub fn new_v4() -> Self {
130 unsafe { Self::new_unchecked(Uuid::new_v4()) }
132 }
133
134 #[cfg(feature = "v5")]
138 pub fn new_v5(namespace: &Uuid, name: &[u8]) -> Self {
139 unsafe { Self::new_unchecked(Uuid::new_v5(namespace, name)) }
141 }
142
143 #[cfg(feature = "v6")]
147 pub fn new_v6(ts: crate::Timestamp, node_id: &[u8; 6]) -> Self {
148 unsafe { Self::new_unchecked(Uuid::new_v6(ts, node_id)) }
150 }
151
152 #[cfg(all(feature = "v6", feature = "std", feature = "rng"))]
156 pub fn now_v6(node_id: &[u8; 6]) -> Self {
157 unsafe { Self::new_unchecked(Uuid::now_v6(node_id)) }
159 }
160
161 #[cfg(feature = "v7")]
165 pub fn new_v7(ts: crate::Timestamp) -> Self {
166 unsafe { Self::new_unchecked(Uuid::new_v7(ts)) }
168 }
169
170 #[cfg(all(feature = "v7", feature = "std"))]
174 pub fn now_v7() -> Self {
175 unsafe { Self::new_unchecked(Uuid::now_v7()) }
177 }
178
179 #[cfg(feature = "v8")]
183 pub const fn new_v8(bytes: [u8; 16]) -> Self {
184 unsafe { Self::new_unchecked(Uuid::new_v8(bytes)) }
186 }
187}
188
189impl From<NonNilUuid> for Uuid {
190 fn from(non_nil: NonNilUuid) -> Self {
202 Uuid::from_u128(non_nil.0.get())
203 }
204}
205
206impl TryFrom<Uuid> for NonNilUuid {
207 type Error = Error;
208
209 fn try_from(uuid: Uuid) -> Result<Self, Self::Error> {
218 NonZeroU128::new(uuid.as_u128())
219 .map(Self)
220 .ok_or(Error(ErrorKind::Nil))
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 #[test]
229 fn test_non_nil_with_option_size() {
230 assert_eq!(
231 std::mem::size_of::<Option<NonNilUuid>>(),
232 std::mem::size_of::<Uuid>()
233 );
234 }
235
236 #[test]
237 fn test_non_nil() {
238 let uuid = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
239
240 assert_eq!(Uuid::from(NonNilUuid::try_from(uuid).unwrap()), uuid);
241 assert_eq!(NonNilUuid::new(uuid).unwrap(), uuid);
242 assert_eq!(unsafe { NonNilUuid::new_unchecked(uuid) }, uuid);
243
244 assert!(NonNilUuid::try_from(Uuid::nil()).is_err());
245 assert!(NonNilUuid::new(Uuid::nil()).is_none());
246 }
247
248 #[test]
249 fn test_non_nil_formatting() {
250 let uuid = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
251 let non_nil = NonNilUuid::try_from(uuid).unwrap();
252
253 assert_eq!(format!("{uuid}"), format!("{non_nil}"));
254 assert_eq!(format!("{uuid:?}"), format!("{non_nil:?}"));
255 }
256
257 #[test]
258 fn test_non_nil_ord() {
259 let uuid1 = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
260 let uuid2 = Uuid::from_u128(0x0123456789abcdef0123456789abcdf0);
261
262 let non_nil1 = NonNilUuid::try_from(uuid1).unwrap();
263 let non_nil2 = NonNilUuid::try_from(uuid2).unwrap();
264
265 assert!(non_nil1 < non_nil2);
267 assert!(non_nil2 > non_nil1);
268
269 assert!(non_nil1 < uuid2);
271 assert!(non_nil2 > uuid1);
272
273 assert!(uuid1 < non_nil2);
275 assert!(uuid2 > non_nil1);
276
277 let non_nil1_copy = NonNilUuid::try_from(uuid1).unwrap();
279 assert_eq!(non_nil1, non_nil1_copy);
280 assert!(non_nil1 <= non_nil1_copy);
281 assert!(non_nil1 >= non_nil1_copy);
282
283 assert_eq!(non_nil1, uuid1);
285 assert_eq!(uuid1, non_nil1);
286 assert!(non_nil1 >= uuid1);
287 assert!(non_nil1 <= uuid1);
288 assert!(uuid1 >= non_nil1);
289 assert!(uuid1 <= non_nil1);
290 }
291}