Skip to content

Commit 0a46a93

Browse files
authored
Use and improve internal iteration support (#71)
* Use and improve internal iteration support * Specialize rfold too
1 parent f1799ec commit 0a46a93

File tree

7 files changed

+132
-44
lines changed

7 files changed

+132
-44
lines changed

src/hex.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
//! ```
1616
//!
1717
18-
use {ArrayLength, GenericArray};
1918
use core::cmp::min;
2019
use core::fmt;
2120
use core::ops::Add;
2221
use core::str;
2322
use typenum::*;
23+
use {ArrayLength, GenericArray};
2424

2525
static LOWER_CHARS: &'static [u8] = b"0123456789abcdef";
2626
static UPPER_CHARS: &'static [u8] = b"0123456789ABCDEF";
@@ -39,21 +39,23 @@ where
3939
// buffer of 2x number of bytes
4040
let mut res = GenericArray::<u8, Sum<T, T>>::default();
4141

42-
for (i, c) in self.iter().take(max_hex).enumerate() {
42+
self.iter().take(max_hex).enumerate().for_each(|(i, c)| {
4343
res[i * 2] = LOWER_CHARS[(c >> 4) as usize];
4444
res[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
45-
}
45+
});
46+
4647
f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;
4748
} else {
4849
// For large array use chunks of up to 1024 bytes (2048 hex chars)
4950
let mut buf = [0u8; 2048];
5051
let mut digits_left = max_digits;
5152

5253
for chunk in self[..max_hex].chunks(1024) {
53-
for (i, c) in chunk.iter().enumerate() {
54+
chunk.iter().enumerate().for_each(|(i, c)| {
5455
buf[i * 2] = LOWER_CHARS[(c >> 4) as usize];
5556
buf[i * 2 + 1] = LOWER_CHARS[(c & 0xF) as usize];
56-
}
57+
});
58+
5759
let n = min(chunk.len() * 2, digits_left);
5860
f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;
5961
digits_left -= n;
@@ -77,21 +79,23 @@ where
7779
// buffer of 2x number of bytes
7880
let mut res = GenericArray::<u8, Sum<T, T>>::default();
7981

80-
for (i, c) in self.iter().take(max_hex).enumerate() {
82+
self.iter().take(max_hex).enumerate().for_each(|(i, c)| {
8183
res[i * 2] = UPPER_CHARS[(c >> 4) as usize];
8284
res[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
83-
}
85+
});
86+
8487
f.write_str(unsafe { str::from_utf8_unchecked(&res[..max_digits]) })?;
8588
} else {
8689
// For large array use chunks of up to 1024 bytes (2048 hex chars)
8790
let mut buf = [0u8; 2048];
8891
let mut digits_left = max_digits;
8992

9093
for chunk in self[..max_hex].chunks(1024) {
91-
for (i, c) in chunk.iter().enumerate() {
94+
chunk.iter().enumerate().for_each(|(i, c)| {
9295
buf[i * 2] = UPPER_CHARS[(c >> 4) as usize];
9396
buf[i * 2 + 1] = UPPER_CHARS[(c & 0xF) as usize];
94-
}
97+
});
98+
9599
let n = min(chunk.len() * 2, digits_left);
96100
f.write_str(unsafe { str::from_utf8_unchecked(&buf[..n]) })?;
97101
digits_left -= n;

src/impls.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ where
2121
N: ArrayLength<T>,
2222
{
2323
fn clone(&self) -> GenericArray<T, N> {
24-
self.map(|x| x.clone())
24+
self.map(Clone::clone)
2525
}
2626
}
2727

@@ -40,11 +40,7 @@ where
4040
**self == **other
4141
}
4242
}
43-
impl<T: Eq, N> Eq for GenericArray<T, N>
44-
where
45-
N: ArrayLength<T>,
46-
{
47-
}
43+
impl<T: Eq, N> Eq for GenericArray<T, N> where N: ArrayLength<T> {}
4844

4945
impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
5046
where

src/iter.rs

+58-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! `GenericArray` iterator implementation.
22
33
use super::{ArrayLength, GenericArray};
4-
use core::{cmp, ptr, fmt, mem};
54
use core::mem::ManuallyDrop;
5+
use core::{cmp, fmt, mem, ptr};
66

77
/// An iterator that moves out of a `GenericArray`
88
pub struct GenericArrayIter<T, N: ArrayLength<T>> {
@@ -131,6 +131,34 @@ where
131131
}
132132
}
133133

134+
fn fold<B, F>(mut self, init: B, mut f: F) -> B
135+
where
136+
F: FnMut(B, Self::Item) -> B,
137+
{
138+
let ret = unsafe {
139+
let GenericArrayIter {
140+
ref array,
141+
ref mut index,
142+
index_back,
143+
} = self;
144+
145+
let remaining = &array[*index..index_back];
146+
147+
remaining.iter().fold(init, |acc, src| {
148+
let value = ptr::read(src);
149+
150+
*index += 1;
151+
152+
f(acc, value)
153+
})
154+
};
155+
156+
// ensure the drop happens here after iteration
157+
drop(self);
158+
159+
ret
160+
}
161+
134162
#[inline]
135163
fn size_hint(&self) -> (usize, Option<usize>) {
136164
let len = self.len();
@@ -176,6 +204,34 @@ where
176204
None
177205
}
178206
}
207+
208+
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
209+
where
210+
F: FnMut(B, Self::Item) -> B,
211+
{
212+
let ret = unsafe {
213+
let GenericArrayIter {
214+
ref array,
215+
index,
216+
ref mut index_back,
217+
} = self;
218+
219+
let remaining = &array[index..*index_back];
220+
221+
remaining.iter().rfold(init, |acc, src| {
222+
let value = ptr::read(src);
223+
224+
*index_back -= 1;
225+
226+
f(acc, value)
227+
})
228+
};
229+
230+
// ensure the drop happens here after iteration
231+
drop(self);
232+
233+
ret
234+
}
179235
}
180236

181237
impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
@@ -187,4 +243,4 @@ where
187243
}
188244
}
189245

190-
// TODO: Implement `FusedIterator` and `TrustedLen` when stabilized
246+
// TODO: Implement `FusedIterator` and `TrustedLen` when stabilized

src/lib.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ impl<T: Clone, U: Clone> Clone for GenericArrayImplEven<T, U> {
9898
parent1: self.parent1.clone(),
9999
parent2: self.parent2.clone(),
100100
_marker: PhantomData,
101-
}
102101
}
103102
}
103+
}
104104

105105
impl<T: Copy, U: Copy> Copy for GenericArrayImplEven<T, U> {}
106106

@@ -120,9 +120,9 @@ impl<T: Clone, U: Clone> Clone for GenericArrayImplOdd<T, U> {
120120
parent1: self.parent1.clone(),
121121
parent2: self.parent2.clone(),
122122
data: self.data.clone(),
123-
}
124123
}
125124
}
125+
}
126126

127127
impl<T: Copy, U: Copy> Copy for GenericArrayImplOdd<T, U> {}
128128

@@ -298,11 +298,13 @@ where
298298
{
299299
let (destination_iter, position) = destination.iter_position();
300300

301-
for (src, dst) in iter.into_iter().zip(destination_iter) {
302-
ptr::write(dst, src);
301+
iter.into_iter()
302+
.zip(destination_iter)
303+
.for_each(|(src, dst)| {
304+
ptr::write(dst, src);
303305

304-
*position += 1;
305-
}
306+
*position += 1;
307+
});
306308
}
307309

308310
if destination.position < N::to_usize() {
@@ -341,11 +343,11 @@ where
341343
{
342344
let (destination_iter, position) = destination.iter_position();
343345

344-
for (i, dst) in destination_iter.enumerate() {
346+
destination_iter.enumerate().for_each(|(i, dst)| {
345347
ptr::write(dst, f(i));
346348

347349
*position += 1;
348-
}
350+
});
349351
}
350352

351353
destination.into_inner()
@@ -570,11 +572,11 @@ where
570572
{
571573
let (destination_iter, position) = destination.iter_position();
572574

573-
for (dst, src) in destination_iter.zip(iter.into_iter()) {
575+
destination_iter.zip(iter).for_each(|(dst, src)| {
574576
ptr::write(dst, src);
575577

576578
*position += 1;
577-
}
579+
});
578580
}
579581

580582
Some(destination.into_inner())

src/sequence.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! Useful traits for manipulating sequences of data stored in `GenericArray`s
22
33
use super::*;
4-
use core::{mem, ptr};
54
use core::ops::{Add, Sub};
5+
use core::{mem, ptr};
66
use typenum::operator_aliases::*;
77

88
/// Defines some sequence with an associated length and iteration capabilities.
@@ -41,17 +41,15 @@ pub unsafe trait GenericSequence<T>: Sized + IntoIterator {
4141

4242
let (left_array_iter, left_position) = left.iter_position();
4343

44-
FromIterator::from_iter(
45-
left_array_iter
46-
.zip(self.into_iter())
47-
.map(|(l, right_value)| {
44+
FromIterator::from_iter(left_array_iter.zip(self.into_iter()).map(
45+
|(l, right_value)| {
4846
let left_value = ptr::read(l);
4947

5048
*left_position += 1;
5149

5250
f(left_value, right_value)
53-
})
54-
)
51+
},
52+
))
5553
}
5654
}
5755

tests/iter.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ extern crate generic_array;
44
use std::cell::Cell;
55
use std::ops::Drop;
66

7-
use generic_array::GenericArray;
87
use generic_array::typenum::consts::U5;
8+
use generic_array::GenericArray;
99

1010
#[test]
1111
fn test_into_iter_as_slice() {
@@ -92,22 +92,37 @@ fn test_into_iter_flat_map() {
9292
assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
9393
}
9494

95+
#[test]
96+
fn test_into_iter_fold() {
97+
assert_eq!(
98+
arr![i32; 1, 2, 3, 4].into_iter().fold(0, |sum, x| sum + x),
99+
10
100+
);
101+
102+
let mut iter = arr![i32; 0, 1, 2, 3, 4, 5].into_iter();
103+
104+
iter.next();
105+
iter.next_back();
106+
107+
assert_eq!(iter.clone().fold(0, |sum, x| sum + x), 10);
108+
109+
assert_eq!(iter.rfold(0, |sum, x| sum + x), 10);
110+
}
111+
95112
#[test]
96113
fn test_into_iter_drops() {
97114
struct R<'a> {
98-
i: &'a Cell<usize>,
115+
i: &'a Cell<usize>,
99116
}
100117

101118
impl<'a> Drop for R<'a> {
102-
fn drop(&mut self) {
119+
fn drop(&mut self) {
103120
self.i.set(self.i.get() + 1);
104121
}
105122
}
106123

107124
fn r(i: &Cell<usize>) -> R {
108-
R {
109-
i: i
110-
}
125+
R { i: i }
111126
}
112127

113128
fn v(i: &Cell<usize>) -> GenericArray<R, U5> {
@@ -161,4 +176,4 @@ fn assert_covariance() {
161176
i
162177
}
163178
}
164-
*/
179+
*/

tests/mod.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
extern crate generic_array;
55
use core::cell::Cell;
66
use core::ops::{Add, Drop};
7-
use generic_array::GenericArray;
87
use generic_array::functional::*;
98
use generic_array::sequence::*;
109
use generic_array::typenum::{U1, U3, U4, U97};
10+
use generic_array::GenericArray;
1111

1212
#[test]
1313
fn test() {
@@ -124,8 +124,8 @@ fn test_cmp() {
124124
mod impl_serde {
125125
extern crate serde_json;
126126

127-
use generic_array::GenericArray;
128127
use generic_array::typenum::U6;
128+
use generic_array::GenericArray;
129129

130130
#[test]
131131
fn test_serde_implementation() {
@@ -178,20 +178,37 @@ fn test_from_iter() {
178178
#[test]
179179
fn test_sizes() {
180180
#![allow(dead_code)]
181+
use core::ffi::c_void;
181182
use core::mem::{size_of, size_of_val};
182183

184+
#[derive(Debug, Copy, Clone)]
185+
enum E {
186+
V,
187+
V2(i32),
188+
V3 { h: bool, i: i32 },
189+
}
190+
183191
#[derive(Debug, Copy, Clone)]
184192
#[repr(C)]
185193
#[repr(packed)]
186194
struct Test {
187195
t: u16,
188196
s: u32,
197+
mm: bool,
189198
r: u16,
190199
f: u16,
200+
p: (),
191201
o: u32,
202+
ff: *const extern "C" fn(*const char) -> *const c_void,
203+
l: *const c_void,
204+
w: bool,
205+
q: bool,
206+
v: E,
192207
}
193208

194-
assert_eq!(size_of::<Test>(), 14);
209+
assert_eq!(size_of::<E>(), 8);
210+
211+
assert_eq!(size_of::<Test>(), 25 + size_of::<usize>() * 2);
195212

196213
assert_eq!(size_of_val(&arr![u8; 1, 2, 3]), size_of::<u8>() * 3);
197214
assert_eq!(size_of_val(&arr![u32; 1]), size_of::<u32>() * 1);

0 commit comments

Comments
 (0)