|
10 | 10 | mod zipmacro; |
11 | 11 |
|
12 | 12 | use crate::imp_prelude::*; |
| 13 | +use crate::AssignElem; |
13 | 14 | use crate::IntoDimension; |
14 | 15 | use crate::Layout; |
15 | 16 | use crate::NdIndex; |
@@ -579,6 +580,7 @@ pub struct Zip<Parts, D> { |
579 | 580 | layout: Layout, |
580 | 581 | } |
581 | 582 |
|
| 583 | + |
582 | 584 | impl<P, D> Zip<(P,), D> |
583 | 585 | where |
584 | 586 | D: Dimension, |
@@ -990,21 +992,36 @@ macro_rules! map_impl { |
990 | 992 | /// |
991 | 993 | /// Restricted to functions that produce copyable results for technical reasons; other |
992 | 994 | /// cases are not yet implemented. |
993 | | - pub fn apply_collect<R>(self, mut f: impl FnMut($($p::Item,)* ) -> R) -> Array<R, D> |
| 995 | + pub fn apply_collect<R>(self, f: impl FnMut($($p::Item,)* ) -> R) -> Array<R, D> |
994 | 996 | where R: Copy, |
995 | 997 | { |
| 998 | + // To support non-Copy elements, implementation of dropping partial array (on |
| 999 | + // panic) is needed |
| 1000 | + let is_c = self.layout.is(CORDER); |
| 1001 | + let is_f = !is_c && self.layout.is(FORDER); |
| 1002 | + let mut output = Array::maybe_uninit(self.dimension.clone().set_f(is_f)); |
| 1003 | + self.apply_assign_into(&mut output, f); |
996 | 1004 | unsafe { |
997 | | - let is_c = self.layout.is(CORDER); |
998 | | - let is_f = !is_c && self.layout.is(FORDER); |
999 | | - let mut output = Array::maybe_uninit(self.dimension.clone().set_f(is_f)); |
1000 | | - self.and(&mut output) |
1001 | | - .apply(move |$($p, )* output_| { |
1002 | | - std::ptr::write(output_.as_mut_ptr(), f($($p ),*)); |
1003 | | - }); |
1004 | 1005 | output.assume_init() |
1005 | 1006 | } |
1006 | 1007 | } |
1007 | 1008 |
|
| 1009 | + /// Apply and assign the results into the producer `into`, which should have the same |
| 1010 | + /// size as the other inputs. |
| 1011 | + /// |
| 1012 | + /// The producer should have assignable items as dictated by the `AssignElem` trait, |
| 1013 | + /// for example `&mut R`. |
| 1014 | + pub fn apply_assign_into<R, Q>(self, into: Q, mut f: impl FnMut($($p::Item,)* ) -> R) |
| 1015 | + where Q: IntoNdProducer<Dim=D>, |
| 1016 | + Q::Item: AssignElem<R> |
| 1017 | + { |
| 1018 | + self.and(into) |
| 1019 | + .apply(move |$($p, )* output_| { |
| 1020 | + output_.assign_elem(f($($p ),*)); |
| 1021 | + }); |
| 1022 | + } |
| 1023 | + |
| 1024 | + |
1008 | 1025 | ); |
1009 | 1026 |
|
1010 | 1027 | /// Split the `Zip` evenly in two. |
|
0 commit comments