]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | //! This crate implements a structure that can be used as a generic array type.use\r |
2 | //! Core Rust array types `[T; N]` can't be used generically with\r | |
3 | //! respect to `N`, so for example this:\r | |
4 | //!\r | |
5 | //! ```{should_fail}\r | |
6 | //! struct Foo<T, N> {\r | |
7 | //! data: [T; N]\r | |
8 | //! }\r | |
9 | //! ```\r | |
10 | //!\r | |
11 | //! won't work.\r | |
12 | //!\r | |
13 | //! **generic-array** exports a `GenericArray<T,N>` type, which lets\r | |
14 | //! the above be implemented as:\r | |
15 | //!\r | |
16 | //! ```\r | |
17 | //! # use generic_array::{ArrayLength, GenericArray};\r | |
18 | //! struct Foo<T, N: ArrayLength<T>> {\r | |
19 | //! data: GenericArray<T,N>\r | |
20 | //! }\r | |
21 | //! ```\r | |
22 | //!\r | |
23 | //! The `ArrayLength<T>` trait is implemented by default for\r | |
24 | //! [unsigned integer types](../typenum/uint/index.html) from\r | |
25 | //! [typenum](../typenum/index.html).\r | |
26 | //!\r | |
27 | //! For ease of use, an `arr!` macro is provided - example below:\r | |
28 | //!\r | |
29 | //! ```\r | |
30 | //! # #[macro_use]\r | |
31 | //! # extern crate generic_array;\r | |
32 | //! # extern crate typenum;\r | |
33 | //! # fn main() {\r | |
34 | //! let array = arr![u32; 1, 2, 3];\r | |
35 | //! assert_eq!(array[2], 3);\r | |
36 | //! # }\r | |
37 | //! ```\r | |
38 | \r | |
39 | #![deny(missing_docs)]\r | |
40 | #![no_std]\r | |
41 | \r | |
42 | #[cfg(feature = "serde")]\r | |
43 | extern crate serde;\r | |
44 | \r | |
45 | #[cfg(test)]\r | |
46 | extern crate bincode;\r | |
47 | \r | |
48 | pub extern crate typenum;\r | |
49 | \r | |
50 | mod hex;\r | |
51 | mod impls;\r | |
52 | \r | |
53 | #[cfg(feature = "serde")]\r | |
54 | pub mod impl_serde;\r | |
55 | \r | |
56 | use core::iter::FromIterator;\r | |
57 | use core::marker::PhantomData;\r | |
58 | use core::mem::ManuallyDrop;\r | |
59 | use core::ops::{Deref, DerefMut};\r | |
60 | use core::{mem, ptr, slice};\r | |
61 | use typenum::bit::{B0, B1};\r | |
62 | use typenum::uint::{UInt, UTerm, Unsigned};\r | |
63 | \r | |
64 | #[cfg_attr(test, macro_use)]\r | |
65 | pub mod arr;\r | |
66 | pub mod functional;\r | |
67 | pub mod iter;\r | |
68 | pub mod sequence;\r | |
69 | \r | |
70 | use functional::*;\r | |
71 | pub use iter::GenericArrayIter;\r | |
72 | use sequence::*;\r | |
73 | \r | |
74 | /// Trait making `GenericArray` work, marking types to be used as length of an array\r | |
75 | pub unsafe trait ArrayLength<T>: Unsigned {\r | |
76 | /// Associated type representing the array type for the number\r | |
77 | type ArrayType;\r | |
78 | }\r | |
79 | \r | |
80 | unsafe impl<T> ArrayLength<T> for UTerm {\r | |
81 | #[doc(hidden)]\r | |
82 | type ArrayType = ();\r | |
83 | }\r | |
84 | \r | |
85 | /// Internal type used to generate a struct of appropriate size\r | |
86 | #[allow(dead_code)]\r | |
87 | #[repr(C)]\r | |
88 | #[doc(hidden)]\r | |
89 | pub struct GenericArrayImplEven<T, U> {\r | |
90 | parent1: U,\r | |
91 | parent2: U,\r | |
92 | _marker: PhantomData<T>,\r | |
93 | }\r | |
94 | \r | |
95 | impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {\r | |
96 | fn clone(&self) -> GenericArrayImplEven<T, U> {\r | |
97 | GenericArrayImplEven {\r | |
98 | parent1: self.parent1.clone(),\r | |
99 | parent2: self.parent2.clone(),\r | |
100 | _marker: PhantomData,\r | |
101 | }\r | |
102 | }\r | |
103 | }\r | |
104 | \r | |
105 | impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}\r | |
106 | \r | |
107 | /// Internal type used to generate a struct of appropriate size\r | |
108 | #[allow(dead_code)]\r | |
109 | #[repr(C)]\r | |
110 | #[doc(hidden)]\r | |
111 | pub struct GenericArrayImplOdd<T, U> {\r | |
112 | parent1: U,\r | |
113 | parent2: U,\r | |
114 | data: T,\r | |
115 | }\r | |
116 | \r | |
117 | impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {\r | |
118 | fn clone(&self) -> GenericArrayImplOdd<T, U> {\r | |
119 | GenericArrayImplOdd {\r | |
120 | parent1: self.parent1.clone(),\r | |
121 | parent2: self.parent2.clone(),\r | |
122 | data: self.data.clone(),\r | |
123 | }\r | |
124 | }\r | |
125 | }\r | |
126 | \r | |
127 | impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}\r | |
128 | \r | |
129 | unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {\r | |
130 | #[doc(hidden)]\r | |
131 | type ArrayType = GenericArrayImplEven<T, N::ArrayType>;\r | |
132 | }\r | |
133 | \r | |
134 | unsafe impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {\r | |
135 | #[doc(hidden)]\r | |
136 | type ArrayType = GenericArrayImplOdd<T, N::ArrayType>;\r | |
137 | }\r | |
138 | \r | |
139 | /// Struct representing a generic array - `GenericArray<T, N>` works like [T; N]\r | |
140 | #[allow(dead_code)]\r | |
141 | pub struct GenericArray<T, U: ArrayLength<T>> {\r | |
142 | data: U::ArrayType,\r | |
143 | }\r | |
144 | \r | |
145 | unsafe impl<T: Send, N: ArrayLength<T>> Send for GenericArray<T, N> {}\r | |
146 | unsafe impl<T: Sync, N: ArrayLength<T>> Sync for GenericArray<T, N> {}\r | |
147 | \r | |
148 | impl<T, N> Deref for GenericArray<T, N>\r | |
149 | where\r | |
150 | N: ArrayLength<T>,\r | |
151 | {\r | |
152 | type Target = [T];\r | |
153 | \r | |
154 | #[inline(always)]\r | |
155 | fn deref(&self) -> &[T] {\r | |
156 | unsafe { slice::from_raw_parts(self as *const Self as *const T, N::to_usize()) }\r | |
157 | }\r | |
158 | }\r | |
159 | \r | |
160 | impl<T, N> DerefMut for GenericArray<T, N>\r | |
161 | where\r | |
162 | N: ArrayLength<T>,\r | |
163 | {\r | |
164 | #[inline(always)]\r | |
165 | fn deref_mut(&mut self) -> &mut [T] {\r | |
166 | unsafe { slice::from_raw_parts_mut(self as *mut Self as *mut T, N::to_usize()) }\r | |
167 | }\r | |
168 | }\r | |
169 | \r | |
170 | /// Creates an array one element at a time using a mutable iterator\r | |
171 | /// you can write to with `ptr::write`.\r | |
172 | ///\r | |
173 | /// Incremenent the position while iterating to mark off created elements,\r | |
174 | /// which will be dropped if `into_inner` is not called.\r | |
175 | #[doc(hidden)]\r | |
176 | pub struct ArrayBuilder<T, N: ArrayLength<T>> {\r | |
177 | array: ManuallyDrop<GenericArray<T, N>>,\r | |
178 | position: usize,\r | |
179 | }\r | |
180 | \r | |
181 | impl<T, N: ArrayLength<T>> ArrayBuilder<T, N> {\r | |
182 | #[doc(hidden)]\r | |
183 | #[inline]\r | |
184 | pub unsafe fn new() -> ArrayBuilder<T, N> {\r | |
185 | ArrayBuilder {\r | |
186 | array: ManuallyDrop::new(mem::uninitialized()),\r | |
187 | position: 0,\r | |
188 | }\r | |
189 | }\r | |
190 | \r | |
191 | /// Creates a mutable iterator for writing to the array using `ptr::write`.\r | |
192 | ///\r | |
193 | /// Increment the position value given as a mutable reference as you iterate\r | |
194 | /// to mark how many elements have been created.\r | |
195 | #[doc(hidden)]\r | |
196 | #[inline]\r | |
197 | pub unsafe fn iter_position(&mut self) -> (slice::IterMut<T>, &mut usize) {\r | |
198 | (self.array.iter_mut(), &mut self.position)\r | |
199 | }\r | |
200 | \r | |
201 | /// When done writing (assuming all elements have been written to),\r | |
202 | /// get the inner array.\r | |
203 | #[doc(hidden)]\r | |
204 | #[inline]\r | |
205 | pub unsafe fn into_inner(self) -> GenericArray<T, N> {\r | |
206 | let array = ptr::read(&self.array);\r | |
207 | \r | |
208 | mem::forget(self);\r | |
209 | \r | |
210 | ManuallyDrop::into_inner(array)\r | |
211 | }\r | |
212 | }\r | |
213 | \r | |
214 | impl<T, N: ArrayLength<T>> Drop for ArrayBuilder<T, N> {\r | |
215 | fn drop(&mut self) {\r | |
216 | for value in &mut self.array[..self.position] {\r | |
217 | unsafe {\r | |
218 | ptr::drop_in_place(value);\r | |
219 | }\r | |
220 | }\r | |
221 | }\r | |
222 | }\r | |
223 | \r | |
224 | /// Consumes an array.\r | |
225 | ///\r | |
226 | /// Increment the position while iterating and any leftover elements\r | |
227 | /// will be dropped if position does not go to N\r | |
228 | #[doc(hidden)]\r | |
229 | pub struct ArrayConsumer<T, N: ArrayLength<T>> {\r | |
230 | array: ManuallyDrop<GenericArray<T, N>>,\r | |
231 | position: usize,\r | |
232 | }\r | |
233 | \r | |
234 | impl<T, N: ArrayLength<T>> ArrayConsumer<T, N> {\r | |
235 | #[doc(hidden)]\r | |
236 | #[inline]\r | |
237 | pub unsafe fn new(array: GenericArray<T, N>) -> ArrayConsumer<T, N> {\r | |
238 | ArrayConsumer {\r | |
239 | array: ManuallyDrop::new(array),\r | |
240 | position: 0,\r | |
241 | }\r | |
242 | }\r | |
243 | \r | |
244 | /// Creates an iterator and mutable reference to the internal position\r | |
245 | /// to keep track of consumed elements.\r | |
246 | ///\r | |
247 | /// Increment the position as you iterate to mark off consumed elements\r | |
248 | #[doc(hidden)]\r | |
249 | #[inline]\r | |
250 | pub unsafe fn iter_position(&mut self) -> (slice::Iter<T>, &mut usize) {\r | |
251 | (self.array.iter(), &mut self.position)\r | |
252 | }\r | |
253 | }\r | |
254 | \r | |
255 | impl<T, N: ArrayLength<T>> Drop for ArrayConsumer<T, N> {\r | |
256 | fn drop(&mut self) {\r | |
257 | for value in &mut self.array[self.position..N::to_usize()] {\r | |
258 | unsafe {\r | |
259 | ptr::drop_in_place(value);\r | |
260 | }\r | |
261 | }\r | |
262 | }\r | |
263 | }\r | |
264 | \r | |
265 | impl<'a, T: 'a, N> IntoIterator for &'a GenericArray<T, N>\r | |
266 | where\r | |
267 | N: ArrayLength<T>,\r | |
268 | {\r | |
269 | type IntoIter = slice::Iter<'a, T>;\r | |
270 | type Item = &'a T;\r | |
271 | \r | |
272 | fn into_iter(self: &'a GenericArray<T, N>) -> Self::IntoIter {\r | |
273 | self.as_slice().iter()\r | |
274 | }\r | |
275 | }\r | |
276 | \r | |
277 | impl<'a, T: 'a, N> IntoIterator for &'a mut GenericArray<T, N>\r | |
278 | where\r | |
279 | N: ArrayLength<T>,\r | |
280 | {\r | |
281 | type IntoIter = slice::IterMut<'a, T>;\r | |
282 | type Item = &'a mut T;\r | |
283 | \r | |
284 | fn into_iter(self: &'a mut GenericArray<T, N>) -> Self::IntoIter {\r | |
285 | self.as_mut_slice().iter_mut()\r | |
286 | }\r | |
287 | }\r | |
288 | \r | |
289 | impl<T, N> FromIterator<T> for GenericArray<T, N>\r | |
290 | where\r | |
291 | N: ArrayLength<T>,\r | |
292 | {\r | |
293 | fn from_iter<I>(iter: I) -> GenericArray<T, N>\r | |
294 | where\r | |
295 | I: IntoIterator<Item = T>,\r | |
296 | {\r | |
297 | unsafe {\r | |
298 | let mut destination = ArrayBuilder::new();\r | |
299 | \r | |
300 | {\r | |
301 | let (destination_iter, position) = destination.iter_position();\r | |
302 | \r | |
303 | for (src, dst) in iter.into_iter().zip(destination_iter) {\r | |
304 | ptr::write(dst, src);\r | |
305 | \r | |
306 | *position += 1;\r | |
307 | }\r | |
308 | }\r | |
309 | \r | |
310 | if destination.position < N::to_usize() {\r | |
311 | from_iter_length_fail(destination.position, N::to_usize());\r | |
312 | }\r | |
313 | \r | |
314 | destination.into_inner()\r | |
315 | }\r | |
316 | }\r | |
317 | }\r | |
318 | \r | |
319 | #[inline(never)]\r | |
320 | #[cold]\r | |
321 | fn from_iter_length_fail(length: usize, expected: usize) -> ! {\r | |
322 | panic!(\r | |
323 | "GenericArray::from_iter received {} elements but expected {}",\r | |
324 | length, expected\r | |
325 | );\r | |
326 | }\r | |
327 | \r | |
328 | unsafe impl<T, N> GenericSequence<T> for GenericArray<T, N>\r | |
329 | where\r | |
330 | N: ArrayLength<T>,\r | |
331 | Self: IntoIterator<Item = T>,\r | |
332 | {\r | |
333 | type Length = N;\r | |
334 | type Sequence = Self;\r | |
335 | \r | |
336 | fn generate<F>(mut f: F) -> GenericArray<T, N>\r | |
337 | where\r | |
338 | F: FnMut(usize) -> T,\r | |
339 | {\r | |
340 | unsafe {\r | |
341 | let mut destination = ArrayBuilder::new();\r | |
342 | \r | |
343 | {\r | |
344 | let (destination_iter, position) = destination.iter_position();\r | |
345 | \r | |
346 | for (i, dst) in destination_iter.enumerate() {\r | |
347 | ptr::write(dst, f(i));\r | |
348 | \r | |
349 | *position += 1;\r | |
350 | }\r | |
351 | }\r | |
352 | \r | |
353 | destination.into_inner()\r | |
354 | }\r | |
355 | }\r | |
356 | \r | |
357 | #[doc(hidden)]\r | |
358 | fn inverted_zip<B, U, F>(\r | |
359 | self,\r | |
360 | lhs: GenericArray<B, Self::Length>,\r | |
361 | mut f: F,\r | |
362 | ) -> MappedSequence<GenericArray<B, Self::Length>, B, U>\r | |
363 | where\r | |
364 | GenericArray<B, Self::Length>:\r | |
365 | GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,\r | |
366 | Self: MappedGenericSequence<T, U>,\r | |
367 | Self::Length: ArrayLength<B> + ArrayLength<U>,\r | |
368 | F: FnMut(B, Self::Item) -> U,\r | |
369 | {\r | |
370 | unsafe {\r | |
371 | let mut left = ArrayConsumer::new(lhs);\r | |
372 | let mut right = ArrayConsumer::new(self);\r | |
373 | \r | |
374 | let (left_array_iter, left_position) = left.iter_position();\r | |
375 | let (right_array_iter, right_position) = right.iter_position();\r | |
376 | \r | |
377 | FromIterator::from_iter(left_array_iter.zip(right_array_iter).map(|(l, r)| {\r | |
378 | let left_value = ptr::read(l);\r | |
379 | let right_value = ptr::read(r);\r | |
380 | \r | |
381 | *left_position += 1;\r | |
382 | *right_position += 1;\r | |
383 | \r | |
384 | f(left_value, right_value)\r | |
385 | }))\r | |
386 | }\r | |
387 | }\r | |
388 | \r | |
389 | #[doc(hidden)]\r | |
390 | fn inverted_zip2<B, Lhs, U, F>(self, lhs: Lhs, mut f: F) -> MappedSequence<Lhs, B, U>\r | |
391 | where\r | |
392 | Lhs: GenericSequence<B, Length = Self::Length> + MappedGenericSequence<B, U>,\r | |
393 | Self: MappedGenericSequence<T, U>,\r | |
394 | Self::Length: ArrayLength<B> + ArrayLength<U>,\r | |
395 | F: FnMut(Lhs::Item, Self::Item) -> U,\r | |
396 | {\r | |
397 | unsafe {\r | |
398 | let mut right = ArrayConsumer::new(self);\r | |
399 | \r | |
400 | let (right_array_iter, right_position) = right.iter_position();\r | |
401 | \r | |
402 | FromIterator::from_iter(\r | |
403 | lhs.into_iter()\r | |
404 | .zip(right_array_iter)\r | |
405 | .map(|(left_value, r)| {\r | |
406 | let right_value = ptr::read(r);\r | |
407 | \r | |
408 | *right_position += 1;\r | |
409 | \r | |
410 | f(left_value, right_value)\r | |
411 | }),\r | |
412 | )\r | |
413 | }\r | |
414 | }\r | |
415 | }\r | |
416 | \r | |
417 | unsafe impl<T, U, N> MappedGenericSequence<T, U> for GenericArray<T, N>\r | |
418 | where\r | |
419 | N: ArrayLength<T> + ArrayLength<U>,\r | |
420 | GenericArray<U, N>: GenericSequence<U, Length = N>,\r | |
421 | {\r | |
422 | type Mapped = GenericArray<U, N>;\r | |
423 | }\r | |
424 | \r | |
425 | unsafe impl<T, N> FunctionalSequence<T> for GenericArray<T, N>\r | |
426 | where\r | |
427 | N: ArrayLength<T>,\r | |
428 | Self: GenericSequence<T, Item = T, Length = N>,\r | |
429 | {\r | |
430 | fn map<U, F>(self, mut f: F) -> MappedSequence<Self, T, U>\r | |
431 | where\r | |
432 | Self::Length: ArrayLength<U>,\r | |
433 | Self: MappedGenericSequence<T, U>,\r | |
434 | F: FnMut(T) -> U,\r | |
435 | {\r | |
436 | unsafe {\r | |
437 | let mut source = ArrayConsumer::new(self);\r | |
438 | \r | |
439 | let (array_iter, position) = source.iter_position();\r | |
440 | \r | |
441 | FromIterator::from_iter(array_iter.map(|src| {\r | |
442 | let value = ptr::read(src);\r | |
443 | \r | |
444 | *position += 1;\r | |
445 | \r | |
446 | f(value)\r | |
447 | }))\r | |
448 | }\r | |
449 | }\r | |
450 | \r | |
451 | #[inline]\r | |
452 | fn zip<B, Rhs, U, F>(self, rhs: Rhs, f: F) -> MappedSequence<Self, T, U>\r | |
453 | where\r | |
454 | Self: MappedGenericSequence<T, U>,\r | |
455 | Rhs: MappedGenericSequence<B, U, Mapped = MappedSequence<Self, T, U>>,\r | |
456 | Self::Length: ArrayLength<B> + ArrayLength<U>,\r | |
457 | Rhs: GenericSequence<B, Length = Self::Length>,\r | |
458 | F: FnMut(T, Rhs::Item) -> U,\r | |
459 | {\r | |
460 | rhs.inverted_zip(self, f)\r | |
461 | }\r | |
462 | \r | |
463 | fn fold<U, F>(self, init: U, mut f: F) -> U\r | |
464 | where\r | |
465 | F: FnMut(U, T) -> U,\r | |
466 | {\r | |
467 | unsafe {\r | |
468 | let mut source = ArrayConsumer::new(self);\r | |
469 | \r | |
470 | let (array_iter, position) = source.iter_position();\r | |
471 | \r | |
472 | array_iter.fold(init, |acc, src| {\r | |
473 | let value = ptr::read(src);\r | |
474 | \r | |
475 | *position += 1;\r | |
476 | \r | |
477 | f(acc, value)\r | |
478 | })\r | |
479 | }\r | |
480 | }\r | |
481 | }\r | |
482 | \r | |
483 | impl<T, N> GenericArray<T, N>\r | |
484 | where\r | |
485 | N: ArrayLength<T>,\r | |
486 | {\r | |
487 | /// Extracts a slice containing the entire array.\r | |
488 | #[inline]\r | |
489 | pub fn as_slice(&self) -> &[T] {\r | |
490 | self.deref()\r | |
491 | }\r | |
492 | \r | |
493 | /// Extracts a mutable slice containing the entire array.\r | |
494 | #[inline]\r | |
495 | pub fn as_mut_slice(&mut self) -> &mut [T] {\r | |
496 | self.deref_mut()\r | |
497 | }\r | |
498 | \r | |
499 | /// Converts slice to a generic array reference with inferred length;\r | |
500 | ///\r | |
501 | /// Length of the slice must be equal to the length of the array.\r | |
502 | #[inline]\r | |
503 | pub fn from_slice(slice: &[T]) -> &GenericArray<T, N> {\r | |
504 | slice.into()\r | |
505 | }\r | |
506 | \r | |
507 | /// Converts mutable slice to a mutable generic array reference\r | |
508 | ///\r | |
509 | /// Length of the slice must be equal to the length of the array.\r | |
510 | #[inline]\r | |
511 | pub fn from_mut_slice(slice: &mut [T]) -> &mut GenericArray<T, N> {\r | |
512 | slice.into()\r | |
513 | }\r | |
514 | }\r | |
515 | \r | |
516 | impl<'a, T, N: ArrayLength<T>> From<&'a [T]> for &'a GenericArray<T, N> {\r | |
517 | /// Converts slice to a generic array reference with inferred length;\r | |
518 | ///\r | |
519 | /// Length of the slice must be equal to the length of the array.\r | |
520 | #[inline]\r | |
521 | fn from(slice: &[T]) -> &GenericArray<T, N> {\r | |
522 | assert_eq!(slice.len(), N::to_usize());\r | |
523 | \r | |
524 | unsafe { &*(slice.as_ptr() as *const GenericArray<T, N>) }\r | |
525 | }\r | |
526 | }\r | |
527 | \r | |
528 | impl<'a, T, N: ArrayLength<T>> From<&'a mut [T]> for &'a mut GenericArray<T, N> {\r | |
529 | /// Converts mutable slice to a mutable generic array reference\r | |
530 | ///\r | |
531 | /// Length of the slice must be equal to the length of the array.\r | |
532 | #[inline]\r | |
533 | fn from(slice: &mut [T]) -> &mut GenericArray<T, N> {\r | |
534 | assert_eq!(slice.len(), N::to_usize());\r | |
535 | \r | |
536 | unsafe { &mut *(slice.as_mut_ptr() as *mut GenericArray<T, N>) }\r | |
537 | }\r | |
538 | }\r | |
539 | \r | |
540 | impl<T: Clone, N> GenericArray<T, N>\r | |
541 | where\r | |
542 | N: ArrayLength<T>,\r | |
543 | {\r | |
544 | /// Construct a `GenericArray` from a slice by cloning its content\r | |
545 | ///\r | |
546 | /// Length of the slice must be equal to the length of the array\r | |
547 | #[inline]\r | |
548 | pub fn clone_from_slice(list: &[T]) -> GenericArray<T, N> {\r | |
549 | Self::from_exact_iter(list.iter().cloned())\r | |
550 | .expect("Slice must be the same length as the array")\r | |
551 | }\r | |
552 | }\r | |
553 | \r | |
554 | impl<T, N> GenericArray<T, N>\r | |
555 | where\r | |
556 | N: ArrayLength<T>,\r | |
557 | {\r | |
558 | /// Creates a new `GenericArray` instance from an iterator with a known exact size.\r | |
559 | ///\r | |
560 | /// Returns `None` if the size is not equal to the number of elements in the `GenericArray`.\r | |
561 | pub fn from_exact_iter<I>(iter: I) -> Option<Self>\r | |
562 | where\r | |
563 | I: IntoIterator<Item = T>,\r | |
564 | <I as IntoIterator>::IntoIter: ExactSizeIterator,\r | |
565 | {\r | |
566 | let iter = iter.into_iter();\r | |
567 | \r | |
568 | if iter.len() == N::to_usize() {\r | |
569 | unsafe {\r | |
570 | let mut destination = ArrayBuilder::new();\r | |
571 | \r | |
572 | {\r | |
573 | let (destination_iter, position) = destination.iter_position();\r | |
574 | \r | |
575 | for (dst, src) in destination_iter.zip(iter.into_iter()) {\r | |
576 | ptr::write(dst, src);\r | |
577 | \r | |
578 | *position += 1;\r | |
579 | }\r | |
580 | }\r | |
581 | \r | |
582 | Some(destination.into_inner())\r | |
583 | }\r | |
584 | } else {\r | |
585 | None\r | |
586 | }\r | |
587 | }\r | |
588 | }\r | |
589 | \r | |
590 | /// A reimplementation of the `transmute` function, avoiding problems\r | |
591 | /// when the compiler can't prove equal sizes.\r | |
592 | #[inline]\r | |
593 | #[doc(hidden)]\r | |
594 | pub unsafe fn transmute<A, B>(a: A) -> B {\r | |
595 | let b = ::core::ptr::read(&a as *const A as *const B);\r | |
596 | ::core::mem::forget(a);\r | |
597 | b\r | |
598 | }\r | |
599 | \r | |
600 | #[cfg(test)]\r | |
601 | mod test {\r | |
602 | // Compile with:\r | |
603 | // cargo rustc --lib --profile test --release --\r | |
604 | // -C target-cpu=native -C opt-level=3 --emit asm\r | |
605 | // and view the assembly to make sure test_assembly generates\r | |
606 | // SIMD instructions instead of a niave loop.\r | |
607 | \r | |
608 | #[inline(never)]\r | |
609 | pub fn black_box<T>(val: T) -> T {\r | |
610 | use core::{mem, ptr};\r | |
611 | \r | |
612 | let ret = unsafe { ptr::read_volatile(&val) };\r | |
613 | mem::forget(val);\r | |
614 | ret\r | |
615 | }\r | |
616 | \r | |
617 | #[test]\r | |
618 | fn test_assembly() {\r | |
619 | use functional::*;\r | |
620 | \r | |
621 | let a = black_box(arr![i32; 1, 3, 5, 7]);\r | |
622 | let b = black_box(arr![i32; 2, 4, 6, 8]);\r | |
623 | \r | |
624 | let c = (&a).zip(b, |l, r| l + r);\r | |
625 | \r | |
626 | let d = a.fold(0, |a, x| a + x);\r | |
627 | \r | |
628 | assert_eq!(c, arr![i32; 3, 7, 11, 15]);\r | |
629 | \r | |
630 | assert_eq!(d, 16);\r | |
631 | }\r | |
632 | }\r |