generic_cast/
lib.rs

1use std::any::TypeId;
2use std::mem::size_of;
3
4pub fn equals<U: 'static, V: 'static>() -> bool {
5    TypeId::of::<U>() == TypeId::of::<V>() && size_of::<U>() == size_of::<V>()
6}
7
8pub fn cast_ref<U: 'static, V: 'static>(u: &U) -> Option<&V> {
9    if equals::<U, V>() {
10        Some(unsafe { std::mem::transmute::<&U, &V>(u) })
11    } else {
12        None
13    }
14}
15
16pub fn cast_mut<U: 'static, V: 'static>(u: &mut U) -> Option<&mut V> {
17    if equals::<U, V>() {
18        Some(unsafe { std::mem::transmute::<&mut U, &mut V>(u) })
19    } else {
20        None
21    }
22}
23
24#[cfg(test)]
25mod tests {
26    use super::*;
27
28    #[test]
29    fn test_equals() {
30        assert!(equals::<u32, u32>());
31        type SameAsU32 = u32;
32        assert!(equals::<u32, SameAsU32>());
33        assert!(!equals::<u32, u64>());
34        assert!(!equals::<Option<u64>, u64>());
35        type OptionU64 = Option<u64>;
36        assert!(equals::<Option<u64>, OptionU64>());
37    }
38
39    #[test]
40    fn test_cast() {
41        let a: u32 = 10;
42        assert!(cast_ref::<_, u32>(&a).is_some());
43        assert_eq!(*cast_ref::<_, u32>(&a).unwrap(), 10);
44        assert!(cast_ref::<_, u64>(&a).is_none());
45    }
46}