typeid_cast/
lib.rs

1use std::{any::TypeId, mem::ManuallyDrop};
2
3/// Safe cast using [`TypeId`].
4#[inline]
5pub fn cast<T: 'static, R: 'static>(t: T) -> Result<R, T> {
6    if TypeId::of::<T>() == TypeId::of::<R>() {
7        union U<T, R> {
8            t: ManuallyDrop<T>,
9            r: ManuallyDrop<R>,
10        }
11
12        // SAFETY: we've confirmed the types are the same.
13        Ok(unsafe { ManuallyDrop::into_inner(U { t: ManuallyDrop::new(t) }.r) })
14    } else {
15        Err(t)
16    }
17}
18
19#[cfg(test)]
20mod test {
21    use super::*;
22
23    #[test]
24    fn test_cast() {
25        assert_eq!(cast::<_, &'static str>("foo"), Ok("foo"));
26        assert_eq!(cast::<_, &'static str>(4), Err(4));
27    }
28}