Skip to content

Commit dc8254e

Browse files
authored
Rollup merge of rust-lang#47142 - sdroege:trusted-random-access-chunks, r=kennytm
Implement TrustedRandomAccess for slice::{Chunks, ChunksMut, Windows} As suggested by @bluss in rust-lang#47115 (comment)
2 parents 9e5787d + b69c124 commit dc8254e

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/libcore/slice/mod.rs

+34
Original file line numberDiff line numberDiff line change
@@ -2117,6 +2117,14 @@ impl<'a, T> ExactSizeIterator for Windows<'a, T> {}
21172117
#[unstable(feature = "fused", issue = "35602")]
21182118
impl<'a, T> FusedIterator for Windows<'a, T> {}
21192119

2120+
#[doc(hidden)]
2121+
unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {
2122+
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
2123+
from_raw_parts(self.v.as_ptr().offset(i as isize), self.size)
2124+
}
2125+
fn may_have_side_effect() -> bool { false }
2126+
}
2127+
21202128
/// An iterator over a slice in (non-overlapping) chunks (`chunk_size` elements at a
21212129
/// time).
21222130
///
@@ -2228,6 +2236,19 @@ impl<'a, T> ExactSizeIterator for Chunks<'a, T> {}
22282236
#[unstable(feature = "fused", issue = "35602")]
22292237
impl<'a, T> FusedIterator for Chunks<'a, T> {}
22302238

2239+
#[doc(hidden)]
2240+
unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {
2241+
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
2242+
let start = i * self.chunk_size;
2243+
let end = match start.checked_add(self.chunk_size) {
2244+
None => self.v.len(),
2245+
Some(end) => cmp::min(end, self.v.len()),
2246+
};
2247+
from_raw_parts(self.v.as_ptr().offset(start as isize), end - start)
2248+
}
2249+
fn may_have_side_effect() -> bool { false }
2250+
}
2251+
22312252
/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size`
22322253
/// elements at a time). When the slice len is not evenly divided by the chunk
22332254
/// size, the last slice of the iteration will be the remainder.
@@ -2331,6 +2352,19 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
23312352
#[unstable(feature = "fused", issue = "35602")]
23322353
impl<'a, T> FusedIterator for ChunksMut<'a, T> {}
23332354

2355+
#[doc(hidden)]
2356+
unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
2357+
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
2358+
let start = i * self.chunk_size;
2359+
let end = match start.checked_add(self.chunk_size) {
2360+
None => self.v.len(),
2361+
Some(end) => cmp::min(end, self.v.len()),
2362+
};
2363+
from_raw_parts_mut(self.v.as_mut_ptr().offset(start as isize), end - start)
2364+
}
2365+
fn may_have_side_effect() -> bool { false }
2366+
}
2367+
23342368
//
23352369
// Free functions
23362370
//

src/libcore/tests/slice.rs

+39
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,18 @@ fn test_chunks_last() {
137137
assert_eq!(c2.last().unwrap()[0], 4);
138138
}
139139

140+
#[test]
141+
fn test_chunks_zip() {
142+
let v1: &[i32] = &[0, 1, 2, 3, 4];
143+
let v2: &[i32] = &[6, 7, 8, 9, 10];
144+
145+
let res = v1.chunks(2)
146+
.zip(v2.chunks(2))
147+
.map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
148+
.collect::<Vec<_>>();
149+
assert_eq!(res, vec![14, 22, 14]);
150+
}
151+
140152
#[test]
141153
fn test_chunks_mut_count() {
142154
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
@@ -176,6 +188,20 @@ fn test_chunks_mut_last() {
176188
assert_eq!(c2.last().unwrap()[0], 4);
177189
}
178190

191+
#[test]
192+
fn test_chunks_mut_zip() {
193+
let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];
194+
let v2: &[i32] = &[6, 7, 8, 9, 10];
195+
196+
for (a, b) in v1.chunks_mut(2).zip(v2.chunks(2)) {
197+
let sum = b.iter().sum::<i32>();
198+
for v in a {
199+
*v += sum;
200+
}
201+
}
202+
assert_eq!(v1, [13, 14, 19, 20, 14]);
203+
}
204+
179205
#[test]
180206
fn test_windows_count() {
181207
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
@@ -215,6 +241,19 @@ fn test_windows_last() {
215241
assert_eq!(c2.last().unwrap()[0], 3);
216242
}
217243

244+
#[test]
245+
fn test_windows_zip() {
246+
let v1: &[i32] = &[0, 1, 2, 3, 4];
247+
let v2: &[i32] = &[6, 7, 8, 9, 10];
248+
249+
let res = v1.windows(2)
250+
.zip(v2.windows(2))
251+
.map(|(a, b)| a.iter().sum::<i32>() + b.iter().sum::<i32>())
252+
.collect::<Vec<_>>();
253+
254+
assert_eq!(res, [14, 18, 22, 26]);
255+
}
256+
218257
#[test]
219258
fn get_range() {
220259
let v: &[i32] = &[0, 1, 2, 3, 4, 5];

0 commit comments

Comments
 (0)