Skip to content

Commit 1ef70a0

Browse files
Add repeat method on slice
1 parent 14ac1b5 commit 1ef70a0

File tree

2 files changed

+72
-53
lines changed

2 files changed

+72
-53
lines changed

src/liballoc/slice.rs

+71
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,77 @@ impl<T> [T] {
17221722
// NB see hack module in this file
17231723
hack::into_vec(self)
17241724
}
1725+
1726+
/// Creates a vector by repeating a slice `n` times.
1727+
///
1728+
/// # Examples
1729+
///
1730+
/// Basic usage:
1731+
///
1732+
/// ```
1733+
/// #![feature(repeat_generic_slice)]
1734+
///
1735+
/// fn main() {
1736+
/// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]);
1737+
/// }
1738+
/// ```
1739+
#[unstable(feature = "repeat_generic_slice",
1740+
reason = "it's on str, why not on slice?",
1741+
issue = "48784")]
1742+
pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy {
1743+
if n == 0 {
1744+
return Vec::new();
1745+
}
1746+
1747+
// If `n` is larger than zero, it can be split as
1748+
// `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
1749+
// `2^expn` is the number represented by the leftmost '1' bit of `n`,
1750+
// and `rem` is the remaining part of `n`.
1751+
1752+
// Using `Vec` to access `set_len()`.
1753+
let mut buf = Vec::with_capacity(self.len() * n);
1754+
1755+
// `2^expn` repetition is done by doubling `buf` `expn`-times.
1756+
buf.extend(self);
1757+
{
1758+
let mut m = n >> 1;
1759+
// If `m > 0`, there are remaining bits up to the leftmost '1'.
1760+
while m > 0 {
1761+
// `buf.extend(buf)`:
1762+
unsafe {
1763+
ptr::copy_nonoverlapping(
1764+
buf.as_ptr(),
1765+
(buf.as_mut_ptr() as *mut T).add(buf.len()),
1766+
buf.len(),
1767+
);
1768+
// `buf` has capacity of `self.len() * n`.
1769+
let buf_len = buf.len();
1770+
buf.set_len(buf_len * 2);
1771+
}
1772+
1773+
m >>= 1;
1774+
}
1775+
}
1776+
1777+
// `rem` (`= n - 2^expn`) repetition is done by copying
1778+
// first `rem` repetitions from `buf` itself.
1779+
let rem_len = self.len() * n - buf.len(); // `self.len() * rem`
1780+
if rem_len > 0 {
1781+
// `buf.extend(buf[0 .. rem_len])`:
1782+
unsafe {
1783+
// This is non-overlapping since `2^expn > rem`.
1784+
ptr::copy_nonoverlapping(
1785+
buf.as_ptr(),
1786+
(buf.as_mut_ptr() as *mut T).add(buf.len()),
1787+
rem_len,
1788+
);
1789+
// `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
1790+
let buf_cap = buf.capacity();
1791+
buf.set_len(buf_cap);
1792+
}
1793+
}
1794+
buf
1795+
}
17251796
}
17261797

17271798
#[lang = "slice_u8"]

src/liballoc/str.rs

+1-53
Original file line numberDiff line numberDiff line change
@@ -2067,59 +2067,7 @@ impl str {
20672067
/// ```
20682068
#[stable(feature = "repeat_str", since = "1.16.0")]
20692069
pub fn repeat(&self, n: usize) -> String {
2070-
if n == 0 {
2071-
return String::new();
2072-
}
2073-
2074-
// If `n` is larger than zero, it can be split as
2075-
// `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
2076-
// `2^expn` is the number represented by the leftmost '1' bit of `n`,
2077-
// and `rem` is the remaining part of `n`.
2078-
2079-
// Using `Vec` to access `set_len()`.
2080-
let mut buf = Vec::with_capacity(self.len() * n);
2081-
2082-
// `2^expn` repetition is done by doubling `buf` `expn`-times.
2083-
buf.extend(self.as_bytes());
2084-
{
2085-
let mut m = n >> 1;
2086-
// If `m > 0`, there are remaining bits up to the leftmost '1'.
2087-
while m > 0 {
2088-
// `buf.extend(buf)`:
2089-
unsafe {
2090-
ptr::copy_nonoverlapping(
2091-
buf.as_ptr(),
2092-
(buf.as_mut_ptr() as *mut u8).add(buf.len()),
2093-
buf.len(),
2094-
);
2095-
// `buf` has capacity of `self.len() * n`.
2096-
let buf_len = buf.len();
2097-
buf.set_len(buf_len * 2);
2098-
}
2099-
2100-
m >>= 1;
2101-
}
2102-
}
2103-
2104-
// `rem` (`= n - 2^expn`) repetition is done by copying
2105-
// first `rem` repetitions from `buf` itself.
2106-
let rem_len = self.len() * n - buf.len(); // `self.len() * rem`
2107-
if rem_len > 0 {
2108-
// `buf.extend(buf[0 .. rem_len])`:
2109-
unsafe {
2110-
// This is non-overlapping since `2^expn > rem`.
2111-
ptr::copy_nonoverlapping(
2112-
buf.as_ptr(),
2113-
(buf.as_mut_ptr() as *mut u8).add(buf.len()),
2114-
rem_len,
2115-
);
2116-
// `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
2117-
let buf_cap = buf.capacity();
2118-
buf.set_len(buf_cap);
2119-
}
2120-
}
2121-
2122-
unsafe { String::from_utf8_unchecked(buf) }
2070+
unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) }
21232071
}
21242072

21252073
/// Checks if all characters in this string are within the ASCII range.

0 commit comments

Comments
 (0)