1use std::{
2 any::{Any, TypeId},
3 marker::PhantomData,
4};
5
6/// Returns a [`TypeId`] for any type regardless of whether it is `'static`.
7///
8/// Note that **this is not the same** as [`TypeId::of`].
9#[inline]
10pub(crate) fn proxy_type_id<T: ?Sized>() -> TypeId {
11 // Return the type ID of a generic closure.
12 Any::type_id(&|| PhantomData::<T>)
13}
14
15/// Returns `true` if the given types are equal.
16#[inline]
17pub(crate) fn is_type_eq<A: ?Sized, B: ?Sized>() -> bool {
18 proxy_type_id::<A>() == proxy_type_id::<B>()
19}
20
21/// Convenience trait for type conversions.
22pub(crate) trait TypeCast {
23 /// Converts a reference if `self` is an instance of `T`.
24 ///
25 /// We require `T: 'static` since we want to ensure when providing a type
26 /// that any lifetimes are static, such as `Cow<str>`.
27 #[inline]
28 fn cast_ref<T: 'static>(&self) -> Option<&T> {
29 if is_type_eq::<Self, T>() {
30 // SAFETY: `self` is `&T`.
31 Some(unsafe { &*(self as *const Self as *const T) })
32 } else {
33 None
34 }
35 }
36}
37
38impl<A> TypeCast for A {}
39