]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
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 | mod [<$id _from>] { | |
60 | use super::*; | |
61 | #[test] | |
62 | fn array() { | |
63 | let vec: $id = Default::default(); | |
64 | ||
65 | // FIXME: Workaround for arrays with more than 32 | |
66 | // elements. | |
67 | // | |
68 | // Safe because we never take a reference to any | |
69 | // uninitialized element. | |
70 | union W { | |
71 | array: [$elem_ty; $elem_count], | |
72 | other: () | |
73 | } | |
74 | let mut array = W { other: () }; | |
75 | for i in 0..$elem_count { | |
76 | let default: $elem_ty = Default::default(); | |
77 | // note: array.other is the active member and | |
78 | // initialized so we can take a reference to it: | |
79 | let p = unsafe { | |
80 | &mut array.other as *mut () as *mut $elem_ty | |
81 | }; | |
82 | // note: default is a valid bit-pattern for | |
83 | // $elem_ty: | |
84 | unsafe { | |
85 | crate::ptr::write(p.wrapping_add(i), default) | |
86 | }; | |
87 | } | |
88 | // note: the array variant of the union is properly | |
89 | // initialized: | |
90 | let mut array = unsafe { | |
91 | array.array | |
92 | }; | |
93 | ||
94 | array[0] = $non_default_array; | |
95 | let vec = vec.replace(0, $non_default_vec); | |
96 | ||
97 | let vec_from_array = $id::from(array); | |
98 | assert_eq!(vec_from_array, vec); | |
99 | let array_from_vec | |
100 | = <[$elem_ty; $elem_count]>::from(vec); | |
101 | // FIXME: Workaround for arrays with more than 32 | |
102 | // elements. | |
103 | for i in 0..$elem_count { | |
104 | assert_eq!(array_from_vec[i], array[i]); | |
105 | } | |
106 | ||
107 | let vec_from_into_array: $id = array.into(); | |
108 | assert_eq!(vec_from_into_array, vec); | |
109 | let array_from_into_vec: [$elem_ty; $elem_count] | |
110 | = vec.into(); | |
111 | // FIXME: Workaround for arrays with more than 32 | |
112 | // elements. | |
113 | for i in 0..$elem_count { | |
114 | assert_eq!(array_from_into_vec[i], array[i]); | |
115 | } | |
116 | } | |
117 | } | |
118 | } | |
119 | } | |
120 | }; | |
121 | } |