rust_bridge_traits/python/
mod.rs

1use std::collections::HashMap;
2
3/// Very similar to the `Into` trait, but we can implement it on foreign types.
4pub trait CustomInto<T> {
5    fn custom_into(self) -> T;
6}
7
8macro_rules! gen_custom_into {
9    ($t1:ty) => {
10        impl CustomInto<$t1> for $t1 {
11            fn custom_into(self) -> $t1 {
12                self
13            }
14        }
15    };
16    (($($T1:ident),+), ($($T2:ident),+), ($($C:tt),+)) => {
17        impl<$($T1, $T2: CustomInto<$T1>),+> CustomInto<($($T1),+,)> for ($($T2),+,) {
18            fn custom_into(self) -> ($($T1),+,) {
19                ($(self.$C.custom_into()),+,)
20            }
21        }
22    }
23}
24
25impl<T1, T2: CustomInto<T1>> CustomInto<Option<T1>> for Option<T2> {
26    fn custom_into(self) -> Option<T1> {
27        self.map(|s| s.custom_into())
28    }
29}
30
31impl<T1, T2: CustomInto<T1>> CustomInto<Vec<T1>> for Vec<T2> {
32    fn custom_into(self) -> Vec<T1> {
33        self.into_iter().map(|x| x.custom_into()).collect()
34    }
35}
36
37impl<K1: std::cmp::Eq + std::hash::Hash, T1, K2: CustomInto<K1>, T2: CustomInto<T1>>
38    CustomInto<HashMap<K1, T1>> for HashMap<K2, T2>
39{
40    fn custom_into(self) -> HashMap<K1, T1> {
41        self.into_iter()
42            .map(|(k, v)| (k.custom_into(), v.custom_into()))
43            .collect()
44    }
45}
46
47impl CustomInto<&'static str> for &str {
48    fn custom_into(self) -> &'static str {
49        // This is how we get around the liftime checker
50        unsafe {
51            let ptr = self as *const str;
52            let ptr = ptr as *mut str;
53            let boxed = Box::from_raw(ptr);
54            Box::leak(boxed)
55        }
56    }
57}
58
59gen_custom_into!((T1), (TT2), (0));
60gen_custom_into!((T1, T2), (TT1, TT2), (0, 1));
61gen_custom_into!((T1, T2, T3), (TT1, TT2, TT3), (0, 1, 2));
62gen_custom_into!((T1, T2, T3, T4), (TT1, TT2, TT3, TT4), (0, 1, 2, 3));
63gen_custom_into!(
64    (T1, T2, T3, T4, T5),
65    (TT1, TT2, TT3, TT4, TT5),
66    (0, 1, 2, 3, 4)
67);
68gen_custom_into!(
69    (T1, T2, T3, T4, T5, T6),
70    (TT1, TT2, TT3, TT4, TT5, TT6),
71    (0, 1, 2, 3, 4, 5)
72);
73
74// There are some restrictions I cannot figure out around conflicting trait
75// implimentations so this is my solution for now
76gen_custom_into!(String);
77
78gen_custom_into!(());
79
80gen_custom_into!(bool);
81
82gen_custom_into!(i8);
83gen_custom_into!(i16);
84gen_custom_into!(i32);
85gen_custom_into!(i64);
86
87gen_custom_into!(u8);
88gen_custom_into!(u16);
89gen_custom_into!(u32);
90gen_custom_into!(u64);
91
92gen_custom_into!(f32);
93gen_custom_into!(f64);