typeid-cast.rs/src/lib.rs

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));
}
}