1 //! Implements `From<[T; N]>` and `Into<[T; N]>` for vector types. 2 3 macro_rules! impl_from_array { 4 ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt 5 | ($non_default_array:expr, $non_default_vec:expr)) => { 6 impl From<[$elem_ty; $elem_count]> for $id { 7 #[inline] 8 fn from(array: [$elem_ty; $elem_count]) -> Self { 9 union U { 10 array: [$elem_ty; $elem_count], 11 vec: $id, 12 } 13 unsafe { U { array }.vec } 14 } 15 } 16 17 impl From<$id> for [$elem_ty; $elem_count] { 18 #[inline] 19 fn from(vec: $id) -> Self { 20 union U { 21 array: [$elem_ty; $elem_count], 22 vec: $id, 23 } 24 unsafe { U { vec }.array } 25 } 26 } 27 28 // FIXME: `Into::into` is not inline, but due to 29 // the blanket impl in `std`, which is not 30 // marked `default`, we cannot override it here with 31 // specialization. 32 /* 33 impl Into<[$elem_ty; $elem_count]> for $id { 34 #[inline] 35 fn into(self) -> [$elem_ty; $elem_count] { 36 union U { 37 array: [$elem_ty; $elem_count], 38 vec: $id, 39 } 40 unsafe { U { vec: self }.array } 41 } 42 } 43 44 impl Into<$id> for [$elem_ty; $elem_count] { 45 #[inline] 46 fn into(self) -> $id { 47 union U { 48 array: [$elem_ty; $elem_count], 49 vec: $id, 50 } 51 unsafe { U { array: self }.vec } 52 } 53 } 54 */ 55 56 test_if! { 57 $test_tt: 58 paste::item! { 59 // Comparisons use integer casts within mantissa^1 range. 60 #[allow(clippy::float_cmp)] 61 mod [<$id _from>] { 62 use super::*; 63 #[test] 64 fn array() { 65 let vec: $id = Default::default(); 66 67 // FIXME: Workaround for arrays with more than 32 68 // elements. 69 // 70 // Safe because we never take a reference to any 71 // uninitialized element. 72 union W { 73 array: [$elem_ty; $elem_count], 74 other: () 75 } 76 let mut array = W { other: () }; 77 for i in 0..$elem_count { 78 let default: $elem_ty = Default::default(); 79 // note: array.other is the active member and 80 // initialized so we can take a reference to it: 81 let p = unsafe { 82 &mut array.other as *mut () as *mut $elem_ty 83 }; 84 // note: default is a valid bit-pattern for 85 // $elem_ty: 86 unsafe { 87 crate::ptr::write(p.wrapping_add(i), default) 88 }; 89 } 90 // note: the array variant of the union is properly 91 // initialized: 92 let mut array = unsafe { 93 array.array 94 }; 95 96 array[0] = $non_default_array; 97 let vec = vec.replace(0, $non_default_vec); 98 99 let vec_from_array = $id::from(array); 100 assert_eq!(vec_from_array, vec); 101 let array_from_vec 102 = <[$elem_ty; $elem_count]>::from(vec); 103 // FIXME: Workaround for arrays with more than 32 104 // elements. 105 for i in 0..$elem_count { 106 assert_eq!(array_from_vec[i], array[i]); 107 } 108 109 let vec_from_into_array: $id = array.into(); 110 assert_eq!(vec_from_into_array, vec); 111 let array_from_into_vec: [$elem_ty; $elem_count] 112 = vec.into(); 113 // FIXME: Workaround for arrays with more than 32 114 // elements. 115 for i in 0..$elem_count { 116 assert_eq!(array_from_into_vec[i], array[i]); 117 } 118 } 119 } 120 } 121 } 122 }; 123 } 124