Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add slice::ExactChunks and ::ExactChunksMut iterators #47126

Merged
merged 11 commits into from
Jan 15, 2018
Merged
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
#![feature(unsize)]
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
#![feature(exact_chunks)]

#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))]
#![cfg_attr(test, feature(test, box_heap))]
Expand Down
74 changes: 74 additions & 0 deletions src/liballoc/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ pub use core::slice::{from_raw_parts, from_raw_parts_mut};
pub use core::slice::{from_ref, from_ref_mut};
#[unstable(feature = "slice_get_slice", issue = "35729")]
pub use core::slice::SliceIndex;
#[unstable(feature = "exact_chunks", issue = "47115")]
pub use core::slice::{ExactChunks, ExactChunksMut};

////////////////////////////////////////////////////////////////////////////////
// Basic slice extension methods
Expand Down Expand Up @@ -611,6 +613,9 @@ impl<T> [T] {
/// not divide the length of the slice, then the last chunk will
/// not have length `chunk_size`.
///
/// See [`exact_chunks`] for a variant of this iterator that returns chunks
/// of always exactly `chunk_size` elements.
///
/// # Panics
///
/// Panics if `chunk_size` is 0.
Expand All @@ -631,11 +636,44 @@ impl<T> [T] {
core_slice::SliceExt::chunks(self, chunk_size)
}

/// Returns an iterator over `chunk_size` elements of the slice at a
/// time. The chunks are slices and do not overlap. If `chunk_size` does
/// not divide the length of the slice, then the last up to `chunk_size-1`
/// elements will be omitted.
///
/// Due to each chunk having exactly `chunk_size` elements, the compiler
/// can often optimize the resulting code better than in the case of
/// [`chunks`].
Copy link
Contributor

@Kerollmops Kerollmops Jan 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, it seems this is not referenced, resulting in a broken link.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, thanks for noticing. I'll submit a PR later, not sure yet why... or why rustdoc does not error out on broken links. Oh well :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah understood why!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why ? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See sdroege@1756f68 . It seems like you have to provide "full" paths somewhere in your doc chunk for "shortened" links. rustdoc doesn't seem to check the current scope for things with the same name.

Copy link
Contributor

@Kerollmops Kerollmops Jan 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I knew well why, you didn't reference the links in the scope :)
I asked more for:

why rustdoc does not error out on broken links

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should.....

///
/// # Panics
///
/// Panics if `chunk_size` is 0.
///
/// # Examples
///
/// ```
/// #![feature(exact_chunks)]
///
/// let slice = ['l', 'o', 'r', 'e', 'm'];
/// let mut iter = slice.exact_chunks(2);
/// assert_eq!(iter.next().unwrap(), &['l', 'o']);
/// assert_eq!(iter.next().unwrap(), &['r', 'e']);
/// assert!(iter.next().is_none());
/// ```
#[unstable(feature = "exact_chunks", issue = "47115")]
#[inline]
pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
core_slice::SliceExt::exact_chunks(self, chunk_size)
}

/// Returns an iterator over `chunk_size` elements of the slice at a time.
/// The chunks are mutable slices, and do not overlap. If `chunk_size` does
/// not divide the length of the slice, then the last chunk will not
/// have length `chunk_size`.
///
/// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
/// of always exactly `chunk_size` elements.
///
/// # Panics
///
/// Panics if `chunk_size` is 0.
Expand All @@ -660,6 +698,42 @@ impl<T> [T] {
core_slice::SliceExt::chunks_mut(self, chunk_size)
}

/// Returns an iterator over `chunk_size` elements of the slice at a time.
/// The chunks are mutable slices, and do not overlap. If `chunk_size` does
/// not divide the length of the slice, then the last up to `chunk_size-1`
/// elements will be omitted.
///
///
/// Due to each chunk having exactly `chunk_size` elements, the compiler
/// can often optimize the resulting code better than in the case of
/// [`chunks_mut`].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broken too.

///
/// # Panics
///
/// Panics if `chunk_size` is 0.
///
/// # Examples
///
/// ```
/// #![feature(exact_chunks)]
///
/// let v = &mut [0, 0, 0, 0, 0];
/// let mut count = 1;
///
/// for chunk in v.exact_chunks_mut(2) {
/// for elem in chunk.iter_mut() {
/// *elem += count;
/// }
/// count += 1;
/// }
/// assert_eq!(v, &[1, 1, 2, 2, 0]);
/// ```
#[unstable(feature = "exact_chunks", issue = "47115")]
#[inline]
pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
core_slice::SliceExt::exact_chunks_mut(self, chunk_size)
}

/// Divides one slice into two at an index.
///
/// The first will contain all indices from `[0, mid)` (excluding
Expand Down
1 change: 1 addition & 0 deletions src/liballoc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#![feature(string_retain)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(exact_chunks)]

extern crate alloc_system;
extern crate std_unicode;
Expand Down
60 changes: 58 additions & 2 deletions src/liballoc/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,30 @@ fn test_chunksator_0() {
let _it = v.chunks(0);
}

#[test]
fn test_exact_chunksator() {
let v = &[1, 2, 3, 4, 5];

assert_eq!(v.exact_chunks(2).len(), 2);

let chunks: &[&[_]] = &[&[1, 2], &[3, 4]];
assert_eq!(v.exact_chunks(2).collect::<Vec<_>>(), chunks);
let chunks: &[&[_]] = &[&[1, 2, 3]];
assert_eq!(v.exact_chunks(3).collect::<Vec<_>>(), chunks);
let chunks: &[&[_]] = &[];
assert_eq!(v.exact_chunks(6).collect::<Vec<_>>(), chunks);

let chunks: &[&[_]] = &[&[3, 4], &[1, 2]];
assert_eq!(v.exact_chunks(2).rev().collect::<Vec<_>>(), chunks);
}

#[test]
#[should_panic]
fn test_exact_chunksator_0() {
let v = &[1, 2, 3, 4];
let _it = v.exact_chunks(0);
}

#[test]
fn test_reverse_part() {
let mut values = [1, 2, 3, 4, 5];
Expand Down Expand Up @@ -1124,7 +1148,7 @@ fn test_mut_chunks() {
}
}
let result = [0, 0, 0, 1, 1, 1, 2];
assert!(v == result);
assert_eq!(v, result);
}

#[test]
Expand All @@ -1136,7 +1160,7 @@ fn test_mut_chunks_rev() {
}
}
let result = [2, 2, 2, 1, 1, 1, 0];
assert!(v == result);
assert_eq!(v, result);
}

#[test]
Expand All @@ -1146,6 +1170,38 @@ fn test_mut_chunks_0() {
let _it = v.chunks_mut(0);
}

#[test]
fn test_mut_exact_chunks() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
assert_eq!(v.exact_chunks_mut(2).len(), 3);
for (i, chunk) in v.exact_chunks_mut(3).enumerate() {
for x in chunk {
*x = i as u8;
}
}
let result = [0, 0, 0, 1, 1, 1, 6];
assert_eq!(v, result);
}

#[test]
fn test_mut_exact_chunks_rev() {
let mut v = [0, 1, 2, 3, 4, 5, 6];
for (i, chunk) in v.exact_chunks_mut(3).rev().enumerate() {
for x in chunk {
*x = i as u8;
}
}
let result = [1, 1, 1, 0, 0, 0, 6];
assert_eq!(v, result);
}

#[test]
#[should_panic]
fn test_mut_exact_chunks_0() {
let mut v = [1, 2, 3, 4];
let _it = v.exact_chunks_mut(0);
}

#[test]
fn test_mut_last() {
let mut x = [1, 2, 3, 4, 5];
Expand Down
Loading