about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-04-24 03:31:11 +0000
committerbors <bors@rust-lang.org>2018-04-24 03:31:11 +0000
commitf305b025cf907d0bbdd2135ec59d89cd32e5cbe9 (patch)
tree56355854a989c4b9dcebd7c8576885961d6342ad /src/liballoc
parenta1286f6835ade2d46b936100acd82d44093b3b68 (diff)
parent3c1fea9c0de008d105e8e043b53c4aba57d0df65 (diff)
downloadrust-f305b025cf907d0bbdd2135ec59d89cd32e5cbe9.tar.gz
rust-f305b025cf907d0bbdd2135ec59d89cd32e5cbe9.zip
Auto merge of #48999 - GuillaumeGomez:add-repeat-on-slice, r=Kimundi
Add repeat method on slice

Fixes #48784.
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/repeat-generic-slice.rs19
-rw-r--r--src/liballoc/slice.rs71
-rw-r--r--src/liballoc/str.rs54
3 files changed, 91 insertions, 53 deletions
diff --git a/src/liballoc/repeat-generic-slice.rs b/src/liballoc/repeat-generic-slice.rs
new file mode 100644
index 00000000000..5c14ee4fd83
--- /dev/null
+++ b/src/liballoc/repeat-generic-slice.rs
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(repeat_generic_slice)]
+
+fn main() {
+    assert_eq!([1, 2].repeat(2), vec![1, 2, 1, 2]);
+    assert_eq!([1, 2, 3, 4].repeat(0), vec![]);
+    assert_eq!([1, 2, 3, 4].repeat(1), vec![1, 2, 3, 4]);
+    assert_eq!([1, 2, 3, 4].repeat(3),
+               vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]);
+}
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 4594263c01f..d50a3458f20 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -394,6 +394,77 @@ impl<T> [T] {
         // NB see hack module in this file
         hack::into_vec(self)
     }
+
+    /// Creates a vector by repeating a slice `n` times.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(repeat_generic_slice)]
+    ///
+    /// fn main() {
+    ///     assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]);
+    /// }
+    /// ```
+    #[unstable(feature = "repeat_generic_slice",
+               reason = "it's on str, why not on slice?",
+               issue = "48784")]
+    pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy {
+        if n == 0 {
+            return Vec::new();
+        }
+
+        // If `n` is larger than zero, it can be split as
+        // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
+        // `2^expn` is the number represented by the leftmost '1' bit of `n`,
+        // and `rem` is the remaining part of `n`.
+
+        // Using `Vec` to access `set_len()`.
+        let mut buf = Vec::with_capacity(self.len() * n);
+
+        // `2^expn` repetition is done by doubling `buf` `expn`-times.
+        buf.extend(self);
+        {
+            let mut m = n >> 1;
+            // If `m > 0`, there are remaining bits up to the leftmost '1'.
+            while m > 0 {
+                // `buf.extend(buf)`:
+                unsafe {
+                    ptr::copy_nonoverlapping(
+                        buf.as_ptr(),
+                        (buf.as_mut_ptr() as *mut T).add(buf.len()),
+                        buf.len(),
+                    );
+                    // `buf` has capacity of `self.len() * n`.
+                    let buf_len = buf.len();
+                    buf.set_len(buf_len * 2);
+                }
+
+                m >>= 1;
+            }
+        }
+
+        // `rem` (`= n - 2^expn`) repetition is done by copying
+        // first `rem` repetitions from `buf` itself.
+        let rem_len = self.len() * n - buf.len(); // `self.len() * rem`
+        if rem_len > 0 {
+            // `buf.extend(buf[0 .. rem_len])`:
+            unsafe {
+                // This is non-overlapping since `2^expn > rem`.
+                ptr::copy_nonoverlapping(
+                    buf.as_ptr(),
+                    (buf.as_mut_ptr() as *mut T).add(buf.len()),
+                    rem_len,
+                );
+                // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
+                let buf_cap = buf.capacity();
+                buf.set_len(buf_cap);
+            }
+        }
+        buf
+    }
 }
 
 #[cfg_attr(stage0, lang = "slice_u8")]
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 82ba2f45711..cac94edf649 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -436,59 +436,7 @@ impl str {
     /// ```
     #[stable(feature = "repeat_str", since = "1.16.0")]
     pub fn repeat(&self, n: usize) -> String {
-        if n == 0 {
-            return String::new();
-        }
-
-        // If `n` is larger than zero, it can be split as
-        // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
-        // `2^expn` is the number represented by the leftmost '1' bit of `n`,
-        // and `rem` is the remaining part of `n`.
-
-        // Using `Vec` to access `set_len()`.
-        let mut buf = Vec::with_capacity(self.len() * n);
-
-        // `2^expn` repetition is done by doubling `buf` `expn`-times.
-        buf.extend(self.as_bytes());
-        {
-            let mut m = n >> 1;
-            // If `m > 0`, there are remaining bits up to the leftmost '1'.
-            while m > 0 {
-                // `buf.extend(buf)`:
-                unsafe {
-                    ptr::copy_nonoverlapping(
-                        buf.as_ptr(),
-                        (buf.as_mut_ptr() as *mut u8).add(buf.len()),
-                        buf.len(),
-                    );
-                    // `buf` has capacity of `self.len() * n`.
-                    let buf_len = buf.len();
-                    buf.set_len(buf_len * 2);
-                }
-
-                m >>= 1;
-            }
-        }
-
-        // `rem` (`= n - 2^expn`) repetition is done by copying
-        // first `rem` repetitions from `buf` itself.
-        let rem_len = self.len() * n - buf.len(); // `self.len() * rem`
-        if rem_len > 0 {
-            // `buf.extend(buf[0 .. rem_len])`:
-            unsafe {
-                // This is non-overlapping since `2^expn > rem`.
-                ptr::copy_nonoverlapping(
-                    buf.as_ptr(),
-                    (buf.as_mut_ptr() as *mut u8).add(buf.len()),
-                    rem_len,
-                );
-                // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
-                let buf_cap = buf.capacity();
-                buf.set_len(buf_cap);
-            }
-        }
-
-        unsafe { String::from_utf8_unchecked(buf) }
+        unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) }
     }
 
     /// Returns a copy of this string where each character is mapped to its