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}