29 lines
673 B
Rust
29 lines
673 B
Rust
use std::{any::TypeId, mem::ManuallyDrop};
|
|
|
|
/// Safe cast using [`TypeId`].
|
|
#[inline]
|
|
pub fn cast<T: 'static, R: 'static>(t: T) -> Result<R, T> {
|
|
if TypeId::of::<T>() == TypeId::of::<R>() {
|
|
union U<T, R> {
|
|
t: ManuallyDrop<T>,
|
|
r: ManuallyDrop<R>,
|
|
}
|
|
|
|
// SAFETY: we've confirmed the types are the same.
|
|
Ok(unsafe { ManuallyDrop::into_inner(U { t: ManuallyDrop::new(t) }.r) })
|
|
} else {
|
|
Err(t)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_cast() {
|
|
assert_eq!(cast::<_, &'static str>("foo"), Ok("foo"));
|
|
assert_eq!(cast::<_, &'static str>(4), Err(4));
|
|
}
|
|
}
|