unzip_array_of_tuple/
lib.rs

1/// Unzips an array of tuples like [(i32, i64); N] into two arrays -> ([i32; N], [i64; N])
2/// Useful 
3pub fn unzip_array_of_tuple<T1, T2, const N: usize>(arr: [(T1,T2); N]) -> ([T1; N], [T2; N])
4{
5    use std::mem::{MaybeUninit, self};
6    
7    let mut first: [MaybeUninit<T1>; N] = unsafe {MaybeUninit::uninit().assume_init()};
8    let mut second: [MaybeUninit<T2>; N] = unsafe {MaybeUninit::uninit().assume_init()};
9
10    for (idx, a) in arr.into_iter().enumerate()
11    {
12        first[idx] = MaybeUninit::new(a.0);
13        second[idx] = MaybeUninit::new(a.1);
14    }
15    
16    // should be safe, as MaybeUninit doesn't have Drop
17    unsafe { (mem::transmute_copy(&first), mem::transmute_copy(&second)) }
18}
19
20#[cfg(test)]
21mod tests {
22    use super::*;
23
24    #[test]
25    fn most_basic()
26    {
27        let tmp = [(1,3),(2,4)];
28        let res = unzip_array_of_tuple(tmp);
29        assert_eq!(res, ([1,2],[3,4]));
30    }
31
32    #[test]
33    fn droppable_types()
34    {
35        use String as S;
36        let tmp = [(S::from("1"), S::from("3")),(S::from("2"), S::from("4"))];
37        let res = unzip_array_of_tuple(tmp);
38        assert_eq!(res, ([S::from("1"), S::from("2")], [S::from("3"), S::from("4")]));
39    }
40
41    #[test]
42    fn droppable_types_with_side_effects()
43    {
44        use std::cell::RefCell;
45        let a = RefCell::new(0);
46        {
47            struct Droppy <'a>{
48                d: &'a RefCell<i32>,
49                v: i32,
50            }
51
52            impl <'a> Drop for Droppy<'a>
53            {
54                fn drop(&mut self)
55                {
56                    *self.d.borrow_mut() += self.v;
57                }
58            }
59            let tmp = [(Droppy {d: &a, v: 1}, Droppy {d: &a, v: 3}), (Droppy {d: &a, v: 2}, Droppy {d: &a, v:4})];
60            
61            let res = unzip_array_of_tuple(tmp);
62
63            assert_eq!(res.0[0].v, 1);
64            assert_eq!(res.0[1].v, 2);
65            assert_eq!(res.1[0].v, 3);
66            assert_eq!(res.1[1].v, 4);
67        }
68        assert_eq!(1+2+3+4, *a.borrow());
69
70    }
71
72    #[test]
73    fn long_array()
74    {
75        let tmp = [(349, 20.4); 1000];
76        let res = unzip_array_of_tuple(tmp);
77        assert_eq!(res.0, [349;1000]);
78        assert_eq!(res.1, [20.4;1000]);
79    }
80}