1#![no_std]
67#![deny(
68 bad_style,
69 dead_code,
70 improper_ctypes,
71 non_shorthand_field_patterns,
72 no_mangle_generic_items,
73 overflowing_literals,
74 path_statements,
75 patterns_in_fns_without_body,
76 private_in_public,
77 unconditional_recursion,
78 unused,
79 unused_allocation,
80 unused_comparisons,
81 unused_parens,
82 while_true,
83 missing_debug_implementations,
84 missing_docs,
85 trivial_casts,
86 trivial_numeric_casts,
87 unused_extern_crates,
88 unused_import_braces,
89 unused_qualifications,
90 unused_results
91)]
92#![forbid(unsafe_code)]
93
94use core::marker::PhantomData;
95pub use uuid;
96use uuid::Uuid;
97
98#[derive(Debug, Clone, Copy)]
100pub enum Error {
101 WrongVersion {
104 expected: usize,
106 actual: usize,
108 },
109}
110
111#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
113#[cfg_attr(feature = "serde", serde(transparent))]
114pub struct Id<T, Version>(
115 Uuid,
116 #[cfg_attr(feature = "serde", serde(skip))] PhantomData<(T, Version)>,
117);
118
119impl<T: Eq, Version: Eq> Eq for Id<T, Version> {}
120
121impl<T: Ord, Version: Ord> Ord for Id<T, Version> {
122 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
123 self.0.cmp(&other.0)
124 }
125}
126
127impl<T: PartialOrd, Version: PartialOrd> PartialOrd for Id<T, Version> {
128 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
129 self.0.partial_cmp(&other.0)
130 }
131}
132
133impl<T, Version> Copy for Id<T, Version> {}
134
135impl<T, Version> Clone for Id<T, Version> {
136 fn clone(&self) -> Self {
137 Self(self.0, self.1)
138 }
139}
140
141impl<T, Version> core::fmt::Debug for Id<T, Version> {
142 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
143 f.debug_tuple("Id").field(&self.0).finish()
144 }
145}
146
147impl<T, Version> core::fmt::Display for Id<T, Version> {
148 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
149 write!(f, "{}", self.0)
150 }
151}
152
153impl<T, Version> core::hash::Hash for Id<T, Version> {
154 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
155 self.0.hash(state);
156 }
157}
158
159impl<T, Version> AsRef<Uuid> for Id<T, Version> {
160 fn as_ref(&self) -> &Uuid {
161 &self.0
162 }
163}
164
165impl<T, Version> PartialEq<Id<T, Version>> for Id<T, Version> {
166 fn eq(&self, other: &Id<T, Version>) -> bool {
167 self.0 == other.0
168 }
169}
170
171impl<T, Version> PartialEq<Uuid> for Id<T, Version> {
172 fn eq(&self, other: &Uuid) -> bool {
173 &self.0 == other
174 }
175}
176
177#[cfg(feature = "v1")]
178pub use v1::V1;
179
180#[cfg(feature = "v3")]
181pub use v3::V3;
182
183#[cfg(feature = "v4")]
184pub use v4::V4;
185
186#[cfg(feature = "v5")]
187pub use v5::V5;
188
189#[cfg(all(unstable_uuid, feature = "v6"))]
190pub use v6::V6;
191
192#[cfg(all(unstable_uuid, feature = "v7"))]
193pub use v7::V7;
194
195#[cfg(all(unstable_uuid, feature = "v8"))]
196pub use v8::V8;
197
198#[cfg(feature = "v1")]
199mod v1 {
200 use crate::{Error, Id};
201 use core::marker::PhantomData;
202 use uuid::{Timestamp, Uuid};
203
204 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
206 pub struct V1;
207
208 impl<T> Id<T, V1> {
209 #[allow(clippy::new_without_default)]
211 pub fn new(ts: Timestamp, node_id: &[u8; 6]) -> Self {
212 Self(Uuid::new_v1(ts, node_id), PhantomData)
213 }
214
215 pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
220 if uuid.get_version_num() == 1 {
221 Ok(Id(uuid, PhantomData))
222 } else {
223 Err(Error::WrongVersion {
224 expected: 1,
225 actual: uuid.get_version_num(),
226 })
227 }
228 }
229 }
230
231 #[cfg(test)]
232 mod tests {
233 use super::V1;
234 use crate::Id;
235 use uuid::Timestamp;
236
237 #[test]
238 fn new() {
239 let context = uuid::timestamp::context::Context::new_random();
240 let _ = Id::<u32, V1>::new(Timestamp::now(&context), &[0u8; 6]);
241 }
242 }
243}
244
245#[cfg(feature = "v3")]
246mod v3 {
247 use crate::{Error, Id, Uuid};
248 use core::marker::PhantomData;
249
250 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
252 pub struct V3;
253
254 impl<T> Id<T, V3> {
255 #[allow(clippy::new_without_default)]
257 pub fn new(namespace: &Uuid, name: &[u8]) -> Self {
258 Self(Uuid::new_v3(namespace, name), PhantomData)
259 }
260
261 pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
266 if uuid.get_version_num() == 3 {
267 Ok(Id(uuid, PhantomData))
268 } else {
269 Err(Error::WrongVersion {
270 expected: 3,
271 actual: uuid.get_version_num(),
272 })
273 }
274 }
275 }
276
277 #[cfg(test)]
278 mod tests {
279 use super::V3;
280 use crate::Id;
281 use uuid::Uuid;
282
283 #[test]
284 fn new() {
285 let _ = Id::<u32, V3>::new(&Uuid::NAMESPACE_DNS, &[0u8; 6]);
286 }
287 }
288}
289
290#[cfg(feature = "v4")]
291mod v4 {
292 use crate::{Error, Id, Uuid};
293 use core::marker::PhantomData;
294
295 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
297 pub struct V4;
298
299 impl<T> Id<T, V4> {
300 #[allow(clippy::new_without_default)]
302 pub fn new() -> Self {
303 Self(Uuid::new_v4(), PhantomData)
304 }
305
306 pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
311 if uuid.get_version_num() == 4 {
312 Ok(Id(uuid, PhantomData))
313 } else {
314 Err(Error::WrongVersion {
315 expected: 4,
316 actual: uuid.get_version_num(),
317 })
318 }
319 }
320 }
321
322 #[cfg(test)]
323 mod tests {
324 use super::V4;
325 use crate::Id;
326
327 #[test]
328 fn new() {
329 let _ = Id::<u32, V4>::new();
330 }
331 }
332}
333
334#[cfg(feature = "v5")]
335mod v5 {
336 use crate::{Error, Id, Uuid};
337 use core::marker::PhantomData;
338
339 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
341 pub struct V5;
342
343 impl<T> Id<T, V5> {
344 #[allow(clippy::new_without_default)]
346 pub fn new(namespace: &Uuid, name: &[u8]) -> Self {
347 Self(Uuid::new_v5(namespace, name), PhantomData)
348 }
349
350 pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
355 if uuid.get_version_num() == 5 {
356 Ok(Id(uuid, PhantomData))
357 } else {
358 Err(Error::WrongVersion {
359 expected: 5,
360 actual: uuid.get_version_num(),
361 })
362 }
363 }
364 }
365
366 #[cfg(test)]
367 mod tests {
368 use super::V5;
369 use crate::Id;
370 use uuid::Uuid;
371
372 #[test]
373 fn new() {
374 let _ = Id::<u32, V5>::new(&Uuid::NAMESPACE_DNS, &[0u8; 6]);
375 }
376 }
377}
378
379#[cfg(all(uuid_unstable, feature = "v6"))]
380mod v6 {
381 use crate::{Error, Id};
382 use core::marker::PhantomData;
383 use uuid::{Timestamp, Uuid};
384
385 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
387 pub struct V6;
388
389 impl<T> Id<T, V6> {
390 #[allow(clippy::new_without_default)]
392 pub fn new(ts: Timestamp, node_id: &[u8; 6]) -> Self {
393 Self(Uuid::new_v6(ts, node_id), PhantomData)
394 }
395
396 pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
401 if uuid.get_version_num() == 6 {
402 Ok(Id(uuid, PhantomData))
403 } else {
404 Err(Error::WrongVersion {
405 expected: 6,
406 actual: uuid.get_version_num(),
407 })
408 }
409 }
410 }
411}
412
413#[cfg(all(uuid_unstable, feature = "v7"))]
414mod v7 {
415 use crate::{Error, Id};
416 use core::marker::PhantomData;
417 use uuid::{Timestamp, Uuid};
418
419 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
421 pub struct V7;
422
423 impl<T> Id<T, V7> {
424 #[allow(clippy::new_without_default)]
426 pub fn new(ts: Timestamp) -> Self {
427 Self(Uuid::new_v7(ts), PhantomData)
428 }
429
430 pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
435 if uuid.get_version_num() == 7 {
436 Ok(Id(uuid, PhantomData))
437 } else {
438 Err(Error::WrongVersion {
439 expected: 7,
440 actual: uuid.get_version_num(),
441 })
442 }
443 }
444 }
445}
446
447#[cfg(all(uuid_unstable, feature = "v8"))]
448mod v8 {
449 use crate::{Error, Id, Uuid};
450 use core::marker::PhantomData;
451
452 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
454 pub struct V8;
455
456 impl<T> Id<T, V8> {
457 #[allow(clippy::new_without_default)]
459 pub fn new(buf: [u8; 16]) -> Self {
460 Self(Uuid::new_v8(buf), PhantomData)
461 }
462
463 pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
468 if uuid.get_version_num() == 8 {
469 Ok(Id(uuid, PhantomData))
470 } else {
471 Err(Error::WrongVersion {
472 expected: 8,
473 actual: uuid.get_version_num(),
474 })
475 }
476 }
477 }
478}