about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/slice.rs74
-rw-r--r--src/liballoc/tests/lib.rs1
-rw-r--r--src/liballoc/tests/slice.rs60
4 files changed, 134 insertions, 2 deletions
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 3cc3ea46796..d8ce28695ab 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -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))]
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 2c7bdc427ea..861f72bcf88 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -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
@@ -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.
@@ -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`].
+    ///
+    /// # 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.
@@ -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`].
+    ///
+    /// # 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
diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs
index f1e95883b38..eee229bc6fd 100644
--- a/src/liballoc/tests/lib.rs
+++ b/src/liballoc/tests/lib.rs
@@ -30,6 +30,7 @@
 #![feature(string_retain)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
+#![feature(exact_chunks)]
 
 extern crate alloc_system;
 extern crate std_unicode;
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index 49bdc9e1b90..1a9d26fd1a2 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -946,6 +946,30 @@ fn test_chunksator_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];
     values[1..4].reverse();
@@ -1159,7 +1183,7 @@ fn test_mut_chunks() {
         }
     }
     let result = [0, 0, 0, 1, 1, 1, 2];
-    assert!(v == result);
+    assert_eq!(v, result);
 }
 
 #[test]
@@ -1171,7 +1195,7 @@ fn test_mut_chunks_rev() {
         }
     }
     let result = [2, 2, 2, 1, 1, 1, 0];
-    assert!(v == result);
+    assert_eq!(v, result);
 }
 
 #[test]
@@ -1182,6 +1206,38 @@ fn test_mut_chunks_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];
     let h = x.last_mut();