accursed_unutterable_type_id/
lib.rs

1//! An accursed, unutterable type id.
2//!
3//! Once upon a time, back when time may not have been a human concept but only a vague idea among the
4//! wise, there was [`std::any::TypeId`].
5//!
6//! It was a good type, and many of these early inhabitants of planet earth were quite fond of it.
7//! Yet, there was a fundamental issue in it, that even the elders were not able to resolve: It
8//! required significant magic from the compiler. The peoples back then were no stranger to magic,
9//! but even just the thought of having magic in their type ids caused numerous wars among them.
10//!
11//! After the last and most brutal of the so called "type-id" wars, one especially clever member of
12//! one of the leading clans for type id research had a breakthrough. They found a new method to
13//! implement type ids in user code! Even though their method had a significant disadvantage in that
14//! it had to be implemented using a derive macro (futuristic technology that the elderly have only
15//! dreamt of back then). Yet this change was accepted, and peace among the peoples ensured.
16//!
17//! Using it is as simple as slapping a derive macro on your type
18//! and then getting the type id using [`AccursedUnutterableTypeId::of`].
19//!
20//! ```
21//! use accursed_unutterable_type_id::{AccursedUnutterableTypeId, AccursedUnutterablyTypeIdentified};
22//!
23//! #[derive(AccursedUnutterablyTypeIdentified)]
24//! struct Uwu;
25//!
26//! let type_id = AccursedUnutterableTypeId::of::<Uwu>();
27//! println!("{type_id:?}")
28//! ```
29
30use std::{
31    fmt::{Debug, Formatter},
32    hash::Hash,
33};
34
35pub use accursed_unutterable_type_id_derive::AccursedUnutterablyTypeIdentified;
36
37/// A type that can be identified by a unique `AccursedUnutterableTypeId`.
38///
39/// # Safety
40/// This trait is only allowed to be implemented by the derive macro.
41pub unsafe trait AccursedUnutterablyTypeIdentified: 'static {
42    /// Returns the accursed unutterable type id for the type.
43    ///
44    /// It's suggested to use [`AccursedUnutterableTypeId::of`] instead.
45    fn type_id() -> AccursedUnutterableTypeId;
46}
47
48/// A unique type id for a type. A fancier (less fancy) [`std::any::TypeId`] without any
49/// internal compiler magic!
50///
51/// It can easily be derived for your type. The derive is the only way to implement this trait.
52/// ```
53/// use accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified;
54///
55/// #[derive(AccursedUnutterablyTypeIdentified)]
56/// struct Uwu;
57/// ```
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
59pub struct AccursedUnutterableTypeId(#[doc(hidden)] InternalAccursedUnutterableTypeId);
60
61impl AccursedUnutterableTypeId {
62    #[doc(hidden)]
63    pub fn __internal_new(inner: InternalAccursedUnutterableTypeId) -> Self {
64        Self(inner)
65    }
66}
67
68#[derive(Clone, Copy, PartialEq, Eq, Hash)]
69#[doc(hidden)]
70#[cfg(debug_assertions)]
71// we do a little trolling
72pub struct InternalAccursedUnutterableTypeId(u128, u64, u64);
73
74#[derive(Clone, Copy, PartialEq, Eq, Hash)]
75#[doc(hidden)]
76#[cfg(not(debug_assertions))]
77pub struct InternalAccursedUnutterableTypeId(u64, u64);
78
79#[cfg(debug_assertions)]
80impl InternalAccursedUnutterableTypeId {
81    pub fn __internal_new(s: u64, g: u64) -> Self {
82        Self(0, s, g)
83    }
84    fn inner(self) -> (u64, u64) {
85        (self.1, self.2)
86    }
87}
88
89#[cfg(not(debug_assertions))]
90impl InternalAccursedUnutterableTypeId {
91    pub fn __internal_new(s: u64, g: u64) -> Self {
92        Self(s, g)
93    }
94    fn inner(self) -> (u64, u64) {
95        (self.0, self.1)
96    }
97}
98
99impl Debug for InternalAccursedUnutterableTypeId {
100    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
101        Debug::fmt(&self.inner(), f)
102    }
103}
104
105impl AccursedUnutterableTypeId {
106    /// Returns the accursed unutterable type id for the type.
107    ///
108    /// ```
109    /// use accursed_unutterable_type_id::{AccursedUnutterableTypeId, AccursedUnutterablyTypeIdentified};
110    ///
111    /// #[derive(AccursedUnutterablyTypeIdentified)]
112    /// struct Uwu;
113    ///
114    /// #[derive(AccursedUnutterablyTypeIdentified)]
115    /// struct Owo;
116    ///
117    /// let uwu_id = AccursedUnutterableTypeId::of::<Uwu>();
118    /// let owo_id = AccursedUnutterableTypeId::of::<Owo>();
119    ///
120    /// assert_ne!(uwu_id, owo_id);
121    /// ```
122    pub fn of<T>() -> Self
123    where
124        T: AccursedUnutterablyTypeIdentified,
125    {
126        T::type_id()
127    }
128}
129
130mod __doctest {
131
132    /// ```
133    /// use accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified;
134    ///
135    /// #[derive(AccursedUnutterablyTypeIdentified)]
136    /// struct Uwu<T: 'static, /* const N: usize */> {
137    ///     _x: [T; /* N */ 0],
138    /// }
139    /// ```
140    mod complex {}
141
142    /// ```
143    /// use accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified;
144    ///
145    /// trait Sussy {}
146    ///
147    /// #[derive(AccursedUnutterablyTypeIdentified)]
148    /// struct Uwu<T: Sussy> {
149    ///     _x: T,
150    /// }
151    /// ```
152    mod type_bounds {}
153
154    /// ```
155    /// use accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified;
156    ///
157    /// #[derive(AccursedUnutterablyTypeIdentified)]
158    /// struct Uwu<T> {
159    ///     _x: T,
160    /// }
161    /// ```
162    mod static_ty_param {}
163
164    /// ```
165    /// use accursed_unutterable_type_id::AccursedUnutterablyTypeIdentified;
166    ///
167    /// #[derive(AccursedUnutterablyTypeIdentified)]
168    /// struct Uwu<T> where T: Copy {
169    ///     _x: T,
170    /// }
171    /// ```
172    mod where_clause {}
173
174    /// ```
175    /// use accursed_unutterable_type_id::{AccursedUnutterableTypeId as Id, AccursedUnutterablyTypeIdentified};
176    ///
177    /// #[derive(AccursedUnutterablyTypeIdentified)]
178    /// struct Uwu<T> {
179    ///     _x: T,
180    /// }
181    ///
182    /// #[derive(AccursedUnutterablyTypeIdentified)]
183    /// struct A;
184    /// #[derive(AccursedUnutterablyTypeIdentified)]
185    /// struct B;
186    ///
187    /// assert_ne!(Id::of::<Uwu<A>>(), Id::of::<Uwu<B>>());
188    /// ```
189    mod type_param {}
190}