type_ulid/
lib.rs

1//! A simple crate containing the [`TypeUlid`] trait to allow associating [`Ulid`]
2//! identifiers with Rust types.
3//!
4//! # Example
5//!
6//! ```
7//! # use type_ulid::TypeUlid;
8//! #[derive(TypeUlid)]
9//! #[ulid = "01GNDP9Y66JGBTGTX4XK6M32YB"]
10//! struct MyStruct;
11//! ```
12
13pub use type_ulid_macros::TypeUlid;
14
15pub use ulid::Ulid;
16
17/// Associates a [`Ulid`] ID to a Rust type.
18///
19/// > **⚠️ Warning:** there is nothing enforcing that the [`Ulid`]s returned by different types will
20/// > be different.
21pub trait TypeUlid {
22    /// The type's [`Ulid`].
23    const ULID: Ulid;
24}
25
26/// Allows reading a type's [`Ulid`] from the context of a trait object when the concrete Rust type
27/// is not known at compile time.
28///
29/// This trait is automatically implemented for every type that implements [`TypeUlid`] and is
30/// sealed to make it impossible to implement manually for custom types.
31pub trait TypeUlidDynamic: private::Sealed {
32    fn ulid(&self) -> Ulid;
33}
34
35impl<T: TypeUlid> TypeUlidDynamic for T {
36    fn ulid(&self) -> Ulid {
37        Self::ULID
38    }
39}
40
41mod private {
42    pub trait Sealed {}
43    impl<T: super::TypeUlid> Sealed for T {}
44}
45
46/// Helper to implement [`TypeUlid`] for a given type.
47macro_rules! impl_ulid {
48    ($t:ty, $ulid:expr) => {
49        impl TypeUlid for $t {
50            const ULID: Ulid = Ulid($ulid);
51        }
52    };
53}
54
55impl_ulid!(u8, 2021656255915497896209715855619467037);
56impl_ulid!(u16, 2021656286850311440545371989823754456);
57impl_ulid!(u32, 2021656307245333748489317905921628405);
58impl_ulid!(u64, 2021656323508136892094714468002888594);
59impl_ulid!(u128, 2021656335852505155406924275550256689);
60impl_ulid!(i8, 2021656350234248601146822538398787257);
61impl_ulid!(i16, 2021656360083645642982176250630573575);
62impl_ulid!(i32, 2021656369452494039486156781916363945);
63impl_ulid!(i64, 2021656381591958783376686378772853584);
64impl_ulid!(i128, 2021656392493396182393399991976868589);
65impl_ulid!(str, 2021656464899998250358740287628939875);
66impl_ulid!(char, 2021656477744412248036447704707663978);
67impl_ulid!(std::path::Path, 2021656526298641269718831147547183140);
68impl_ulid!(std::path::PathBuf, 2021656533964195260964832532224399014);
69impl_ulid!(String, 2021656411366161332396897323242175745);
70impl_ulid!(std::ffi::CStr, 2021656593778807277069547360976271384);
71impl_ulid!(std::ffi::CString, 2021656608266244812738352417994302175);
72impl_ulid!(std::ffi::OsStr, 2021656632874440750318571899824814504);
73impl_ulid!(std::ffi::OsString, 2021656640805438832313622968989918986);
74impl_ulid!(std::time::Duration, 2021656695577227212934222356752834404);
75impl_ulid!((), 2021656729314635244986430849253282093);
76
77#[cfg(test)]
78mod test {
79    use super::*;
80
81    #[test]
82    fn type_ulid_dyanmic_is_object_safe() {
83        let _: Box<dyn TypeUlidDynamic> = Box::new(());
84    }
85}