-
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The `TypeCast` trait allows using `cast_ref` as a method. We allow casting from a non-`Any`, which makes it possible to optimize some internals without adding `Any` to more of the public API.
- Loading branch information
Showing
4 changed files
with
49 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use std::{ | ||
any::{Any, TypeId}, | ||
marker::PhantomData, | ||
}; | ||
|
||
/// Returns a [`TypeId`] for any type regardless of whether it is `'static`. | ||
/// | ||
/// Note that **this is not the same** as [`TypeId::of`]. | ||
#[inline] | ||
pub(crate) fn proxy_type_id<T: ?Sized>() -> TypeId { | ||
// Return the type ID of a generic closure. | ||
Any::type_id(&|| PhantomData::<T>) | ||
} | ||
|
||
/// Returns `true` if the given types are equal. | ||
#[inline] | ||
pub(crate) fn is_type_eq<A: ?Sized, B: ?Sized>() -> bool { | ||
proxy_type_id::<A>() == proxy_type_id::<B>() | ||
} | ||
|
||
/// Convenience trait for type conversions. | ||
pub(crate) trait TypeCast { | ||
/// Converts a reference if `self` is an instance of `T`. | ||
/// | ||
/// We require `T: 'static` since we want to ensure when providing a type | ||
/// that any lifetimes are static, such as `Cow<str>`. | ||
#[inline] | ||
fn cast_ref<T: 'static>(&self) -> Option<&T> { | ||
if is_type_eq::<Self, T>() { | ||
// SAFETY: `self` is `&T`. | ||
Some(unsafe { &*(self as *const Self as *const T) }) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
|
||
impl<A> TypeCast for A {} |