| 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 | |