1#[doc(hidden)]
61pub mod reexport {
62 #[inline] pub fn clone<T: Clone>(source: T) -> T { source.clone() }
63 #[inline] pub unsafe fn ptr_write<T>(dst: *mut T, src: T) { ::std::ptr::write(dst, src) }
64 #[inline] pub unsafe fn ptr_read<T>(src: *const T) -> T { ::std::ptr::read(src) }
65 #[inline] pub fn forget<T>(t: T) { ::std::mem::forget(t) }
66 #[inline] pub unsafe fn uninitialized<T>() -> T { ::std::mem::uninitialized() }
67}
68
69#[cfg(feature="use_std")]
70#[macro_export]
71#[doc(hidden)]
72macro_rules! slice_as_array_transmute {
73 ($slice:expr) => { ::std::mem::transmute($slice) }
74}
75
76#[cfg(not(feature="use_std"))]
77#[macro_export]
78macro_rules! slice_as_array_transmute {
79 ($slice:expr) => { ::core::mem::transmute($slice) }
80}
81
82
83#[macro_export]
88macro_rules! slice_as_array {
89 ($slice:expr, [$t:ty ; $len:expr] ) => {{
90 unsafe fn this_transmute(xs: &[$t]) -> &[$t; $len] {
91 slice_as_array_transmute!(xs.as_ptr())
92 }
93
94 let s: &[$t] = $slice;
95 if s.len() == $len {
96 Some( unsafe { this_transmute(s) } )
97 } else {
98 None
99 }
100 }}
101}
102
103#[macro_export]
106macro_rules! slice_as_array_mut {
107 ($slice:expr, [$t:ty ; $len:expr] ) => {{
108 unsafe fn this_transmute(xs: &mut [$t]) -> &mut [$t; $len] {
109 slice_as_array_transmute!(xs.as_mut_ptr())
110 }
111
112 let s: &mut [$t] = $slice;
113 if s.len() == $len {
114 Some( unsafe { this_transmute(s) } )
115 } else {
116 None
117 }
118 }}
119}
120
121#[macro_export]
124macro_rules! slice_to_array_clone {
125 ($slice:expr, [$t:ty ; $len:expr] ) => {{
126 struct SafeArrayInitialization {
127 array: Option<[$t; $len]>,
128 count: usize,
129 }
130 impl SafeArrayInitialization {
131 fn new() -> Self {
132 SafeArrayInitialization { array: Some(unsafe { $crate::reexport::uninitialized() }), count: 0 }
133 }
134 fn init_from_slice(mut self, slice: &[$t]) -> Option<[$t; $len]> {
135 {
136 let array_mut: &mut [$t] = self.array.as_mut().unwrap().as_mut();
137 if slice.len() != array_mut.len() {
138 return None;
139 }
140 debug_assert_eq!(self.count, 0);
141 for (val, ptr) in slice.iter().zip(array_mut.iter_mut()) {
142 let val = $crate::reexport::clone(*val);
143 unsafe { $crate::reexport::ptr_write(ptr, val) };
144 self.count += 1;
145 }
146 }
147 self.array.take()
148 }
149 }
150 impl Drop for SafeArrayInitialization {
151 fn drop(&mut self) {
152 if let Some(mut array) = self.array.take() {
153 let count = self.count;
154 {
155 for ptr in array.as_mut()[..count].iter_mut() {
156 unsafe { $crate::reexport::ptr_read(ptr) };
157 }
158 }
159 $crate::reexport::forget(array);
160 }
161 }
162 }
163
164 SafeArrayInitialization::new().init_from_slice($slice)
165 }}
166}
167
168#[cfg(test)]
169mod test {
170 #[test]
171 fn correct_length() {
172 let xs: [u32; 6] = [1, 2, 4, 8, 16, 32];
173 let xs_prefix: &[u32; 3] = slice_as_array!(&xs[1..4], [u32; 3]).expect("Length mismatch");
174 assert_eq!(xs_prefix, &[2, 4, 8]);
175 }
176
177 #[test]
178 fn incorrect_length() {
179 let xs: [u32; 6] = [1, 2, 4, 8, 16, 32];
180 let xs_prefix: Option<&[u32; 8]> = slice_as_array!(&xs[1..4], [u32; 8]);
181 assert_eq!(xs_prefix, None);
182 }
183
184 #[test]
185 #[should_panic]
186 fn overlong_length() {
187 let xs: [u32; 6] = [1, 2, 4, 8, 16, 32];
188 let xs_prefix: Option<&[u32; 8]> = slice_as_array!(&xs[0..8], [u32; 8]);
189 assert_eq!(xs_prefix, None);
190 }
191
192 #[test]
193 fn zero_length() {
194 let xs: [u32; 6] = [1, 2, 4, 8, 16, 32];
195 let xs_prefix: &[u32; 0] = slice_as_array!(&xs[1..1], [u32; 0]).unwrap();
196 assert_eq!(xs_prefix, &[]);
197 }
198
199 #[test]
200 fn array_of_arrays() {
201 let xs: [[u8; 4]; 3] = [
202 [10,11,12,13],
203 [20,21,22,23],
204 [30,31,32,33],
205 ];
206
207 let xs_suffix: &[[u8;4]; 2] = slice_as_array!(&xs[1..], [[u8; 4]; 2]).unwrap();
208 assert_eq!(xs_suffix[0][0], 20);
209 assert_eq!(xs_suffix[1][3], 33);
210 }
211
212 #[test]
213 fn clone_correct() {
214 let xs: [u32; 6] = [1, 2, 4, 8, 16, 32];
215 let xs_middle: [u32; 3] = slice_to_array_clone!(&xs[1..4], [u32; 3]).expect("Length mismatch");
216 assert_eq!(xs_middle, [2, 4, 8]);
217 }
218
219 #[test]
220 fn clone_wrong_length() {
221 let xs: [u32; 6] = [1, 2, 4, 8, 16, 32];
222 let xs_middle: Option<[u32; 3]> = slice_to_array_clone!(&xs[1..5], [u32; 3]);
223 assert_eq!(xs_middle, None);
224 }
225}