#![no_std]
#![deny(
bad_style,
dead_code,
improper_ctypes,
non_shorthand_field_patterns,
no_mangle_generic_items,
overflowing_literals,
path_statements,
patterns_in_fns_without_body,
private_in_public,
unconditional_recursion,
unused,
unused_allocation,
unused_comparisons,
unused_parens,
while_true,
missing_debug_implementations,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unused_extern_crates,
unused_import_braces,
unused_qualifications,
unused_results
)]
#![forbid(unsafe_code)]
use core::{marker::PhantomData, ops::Deref};
pub use uuid;
use uuid::Uuid;
#[derive(Debug, Clone, Copy)]
pub enum Error {
WrongVersion {
expected: usize,
actual: usize,
},
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Id<T, Version>(
Uuid,
#[cfg_attr(feature = "serde", serde(skip))] PhantomData<(T, Version)>,
);
impl<T: Eq, Version: Eq> Eq for Id<T, Version> {}
impl<T: Ord, Version: Ord> Ord for Id<T, Version> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl<T: PartialOrd, Version: PartialOrd> PartialOrd for Id<T, Version> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl<T, Version> Copy for Id<T, Version> {}
impl<T, Version> Clone for Id<T, Version> {
fn clone(&self) -> Self {
Self(self.0, self.1)
}
}
impl<T, Version> core::fmt::Debug for Id<T, Version> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("Id").field(&self.0).finish()
}
}
impl<T, Version> core::fmt::Display for Id<T, Version> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0)
}
}
impl<T, Version> core::hash::Hash for Id<T, Version> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<T, Version> AsRef<Uuid> for Id<T, Version> {
fn as_ref(&self) -> &Uuid {
&self.0
}
}
impl<T, Version> Deref for Id<T, Version> {
type Target = Uuid;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, Version> PartialEq<Id<T, Version>> for Id<T, Version> {
fn eq(&self, other: &Id<T, Version>) -> bool {
self.0 == other.0
}
}
impl<T, Version> PartialEq<Uuid> for Id<T, Version> {
fn eq(&self, other: &Uuid) -> bool {
&self.0 == other
}
}
#[cfg(feature = "v1")]
pub use v1::V1;
#[cfg(feature = "v3")]
pub use v3::V3;
#[cfg(feature = "v4")]
pub use v4::V4;
#[cfg(feature = "v5")]
pub use v5::V5;
#[cfg(all(unstable_uuid, feature = "v6"))]
pub use v6::V6;
#[cfg(all(unstable_uuid, feature = "v7"))]
pub use v7::V7;
#[cfg(all(unstable_uuid, feature = "v8"))]
pub use v8::V8;
#[cfg(feature = "v1")]
mod v1 {
use crate::{Error, Id};
use core::marker::PhantomData;
use uuid::{Timestamp, Uuid};
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct V1;
impl<T> Id<T, V1> {
#[allow(clippy::new_without_default)]
pub fn new(ts: Timestamp, node_id: &[u8; 6]) -> Self {
Self(Uuid::new_v1(ts, node_id), PhantomData::default())
}
pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
if uuid.get_version_num() == 1 {
Ok(Id(uuid, PhantomData::default()))
} else {
Err(Error::WrongVersion {
expected: 1,
actual: uuid.get_version_num(),
})
}
}
}
#[cfg(test)]
mod tests {
use super::V1;
use crate::Id;
use uuid::Timestamp;
#[test]
fn new() {
let context = uuid::timestamp::context::Context::new_random();
let _ = Id::<u32, V1>::new(Timestamp::now(&context), &[0u8; 6]);
}
}
}
#[cfg(feature = "v3")]
mod v3 {
use crate::{Error, Id, Uuid};
use core::marker::PhantomData;
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct V3;
impl<T> Id<T, V3> {
#[allow(clippy::new_without_default)]
pub fn new(namespace: &Uuid, name: &[u8]) -> Self {
Self(Uuid::new_v3(namespace, name), PhantomData::default())
}
pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
if uuid.get_version_num() == 3 {
Ok(Id(uuid, PhantomData::default()))
} else {
Err(Error::WrongVersion {
expected: 3,
actual: uuid.get_version_num(),
})
}
}
}
#[cfg(test)]
mod tests {
use super::V3;
use crate::Id;
use uuid::Uuid;
#[test]
fn new() {
let _ = Id::<u32, V3>::new(&Uuid::NAMESPACE_DNS, &[0u8; 6]);
}
}
}
#[cfg(feature = "v4")]
mod v4 {
use crate::{Error, Id, Uuid};
use core::marker::PhantomData;
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct V4;
impl<T> Id<T, V4> {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self(Uuid::new_v4(), PhantomData::default())
}
pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
if uuid.get_version_num() == 4 {
Ok(Id(uuid, PhantomData::default()))
} else {
Err(Error::WrongVersion {
expected: 4,
actual: uuid.get_version_num(),
})
}
}
}
#[cfg(test)]
mod tests {
use super::V4;
use crate::Id;
#[test]
fn new() {
let _ = Id::<u32, V4>::new();
}
}
}
#[cfg(feature = "v5")]
mod v5 {
use crate::{Error, Id, Uuid};
use core::marker::PhantomData;
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct V5;
impl<T> Id<T, V5> {
#[allow(clippy::new_without_default)]
pub fn new(namespace: &Uuid, name: &[u8]) -> Self {
Self(Uuid::new_v5(namespace, name), PhantomData::default())
}
pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
if uuid.get_version_num() == 5 {
Ok(Id(uuid, PhantomData::default()))
} else {
Err(Error::WrongVersion {
expected: 5,
actual: uuid.get_version_num(),
})
}
}
}
#[cfg(test)]
mod tests {
use super::V5;
use crate::Id;
use uuid::Uuid;
#[test]
fn new() {
let _ = Id::<u32, V5>::new(&Uuid::NAMESPACE_DNS, &[0u8; 6]);
}
}
}
#[cfg(all(uuid_unstable, feature = "v6"))]
mod v6 {
use crate::{Error, Id};
use core::marker::PhantomData;
use uuid::{Timestamp, Uuid};
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct V6;
impl<T> Id<T, V6> {
#[allow(clippy::new_without_default)]
pub fn new(ts: Timestamp, node_id: &[u8; 6]) -> Self {
Self(Uuid::new_v6(ts, node_id), PhantomData::default())
}
pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
if uuid.get_version_num() == 6 {
Ok(Id(uuid, PhantomData::default()))
} else {
Err(Error::WrongVersion {
expected: 6,
actual: uuid.get_version_num(),
})
}
}
}
}
#[cfg(all(uuid_unstable, feature = "v7"))]
mod v7 {
use crate::{Error, Id};
use core::marker::PhantomData;
use uuid::{Timestamp, Uuid};
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct V7;
impl<T> Id<T, V7> {
#[allow(clippy::new_without_default)]
pub fn new(ts: Timestamp) -> Self {
Self(Uuid::new_v7(ts), PhantomData::default())
}
pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
if uuid.get_version_num() == 7 {
Ok(Id(uuid, PhantomData::default()))
} else {
Err(Error::WrongVersion {
expected: 7,
actual: uuid.get_version_num(),
})
}
}
}
}
#[cfg(all(uuid_unstable, feature = "v8"))]
mod v8 {
use crate::{Error, Id, Uuid};
use core::marker::PhantomData;
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct V8;
impl<T> Id<T, V8> {
#[allow(clippy::new_without_default)]
pub fn new(buf: [u8; 16]) -> Self {
Self(Uuid::new_v8(buf), PhantomData::default())
}
pub fn from_generic_uuid(uuid: Uuid) -> Result<Self, Error> {
if uuid.get_version_num() == 8 {
Ok(Id(uuid, PhantomData::default()))
} else {
Err(Error::WrongVersion {
expected: 8,
actual: uuid.get_version_num(),
})
}
}
}
}