Skip to content

Commit 746c92c

Browse files
committed
remove unsafe code
1 parent 4a6e1eb commit 746c92c

2 files changed

Lines changed: 70 additions & 19 deletions

File tree

src/functional.rs

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,14 @@ where
1313
/// If the mapping function panics, any already initialized elements in the new array will
1414
/// be dropped, AND any unused elements in the source array will also be dropped.
1515
#[inline(always)]
16-
pub fn map<O, F>(self, mut f: F) -> Array<O, U>
16+
pub fn map<O, F>(self, f: F) -> Array<O, U>
1717
where
1818
F: FnMut(T) -> O,
1919
{
20-
let mut out = Array::uninit();
21-
22-
for (i, s) in self.into_iter().enumerate() {
23-
out[i].write(f(s));
24-
}
25-
26-
unsafe { out.assume_init() }
20+
Array::from_iter(Mapper {
21+
inner: self.into_iter(),
22+
f,
23+
})
2724
}
2825

2926
/// Combines two `Array` instances and iterates through both of them, initialization a new
@@ -32,21 +29,16 @@ where
3229
/// If the mapping function panics, any already initialized elements in the new array will
3330
/// be dropped, AND any unused elements in the source arrays will also be dropped.
3431
#[inline(always)]
35-
pub fn zip<Rhs, F, O>(self, rhs: Array<Rhs, U>, mut f: F) -> Array<O, U>
32+
pub fn zip<Rhs, F, O>(self, rhs: Array<Rhs, U>, f: F) -> Array<O, U>
3633
where
3734
U: ArraySize,
3835
F: FnMut(T, Rhs) -> O,
3936
{
40-
let mut out = Array::uninit();
41-
42-
let mut s = self.into_iter().enumerate();
43-
let mut r = rhs.into_iter();
44-
45-
while let (Some((i, s)), Some(r)) = (s.next(), r.next()) {
46-
out[i].write(f(s, r));
47-
}
48-
49-
unsafe { out.assume_init() }
37+
Array::from_iter(Zipper {
38+
inner: self.into_iter(),
39+
rhs: rhs.into_iter(),
40+
f,
41+
})
5042
}
5143

5244
/// Folds (or reduces) a sequence of data into a single value.
@@ -64,3 +56,41 @@ where
6456
init
6557
}
6658
}
59+
60+
struct Mapper<I, F> {
61+
inner: I,
62+
f: F,
63+
}
64+
65+
impl<I, T, O, F> Iterator for Mapper<I, F>
66+
where
67+
I: Iterator<Item = T>,
68+
F: FnMut(T) -> O,
69+
{
70+
type Item = O;
71+
72+
#[inline(always)]
73+
fn next(&mut self) -> Option<Self::Item> {
74+
Some((self.f)(self.inner.next()?))
75+
}
76+
}
77+
78+
struct Zipper<I, R, F> {
79+
inner: I,
80+
rhs: R,
81+
f: F,
82+
}
83+
84+
impl<I, T, R, RT, O, F> Iterator for Zipper<I, R, F>
85+
where
86+
I: Iterator<Item = T>,
87+
R: Iterator<Item = RT>,
88+
F: FnMut(T, RT) -> O,
89+
{
90+
type Item = O;
91+
92+
#[inline(always)]
93+
fn next(&mut self) -> Option<Self::Item> {
94+
Some((self.f)(self.inner.next()?, self.rhs.next()?))
95+
}
96+
}

tests/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,24 @@ fn maybe_uninit() {
139139
let array = unsafe { uninit_array.assume_init() };
140140
assert_eq!(array.as_slice(), EXAMPLE_SLICE);
141141
}
142+
143+
#[test]
144+
fn test_functional_map() {
145+
let base = Array::<u8, U4>::from([1, 2, 3, 4]);
146+
let expected = Array::<u8, U4>::from([2, 3, 4, 5]);
147+
assert_eq!(base.map(|item| item + 1), expected);
148+
}
149+
150+
#[test]
151+
fn test_functional_zip() {
152+
let base = Array::<u8, U4>::from([1, 2, 3, 4]);
153+
let with = Array::<u8, U4>::from([2, 3, 4, 5]);
154+
let expected = Array::<u8, U4>::from([2, 6, 12, 20]);
155+
assert_eq!(base.zip(with, |item, rhs| item * rhs), expected);
156+
}
157+
158+
#[test]
159+
fn test_functional_fold() {
160+
let base = Array::<u8, U4>::from([1, 2, 3, 4]);
161+
assert_eq!(base.fold(0, |acc, item| acc + item), 10);
162+
}

0 commit comments

Comments
 (0)