1 | use 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 ] |
10 | pub(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 ] |
17 | pub(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. |
22 | pub(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 | |
38 | impl<A> TypeCast for A {} |
39 | |