Skip to content

Commit

Permalink
define copy_within on slices
Browse files Browse the repository at this point in the history
This is a safe wrapper around ptr::copy, for regions within a single
slice. Previously, safe in-place copying was only available as a side
effect of Vec::drain.
  • Loading branch information
oconnor663 committed Sep 20, 2018
1 parent 1d33aed commit b3ffd33
Showing 1 changed file with 57 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/libcore/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1618,6 +1618,63 @@ impl<T> [T] {
}
}

/// Copies elements from one part of the slice to another part of itself,
/// using a memmove.
///
/// `src` is the range within `self` to copy from. `dest` is the starting
/// index of the range within `self` to copy to, which will have the same
/// length as `src`. The two ranges may overlap. The ends of the two ranges
/// must be less than or equal to `self.len()`.
///
/// # Panics
///
/// This function will panic if either range exceeds the end of the slice,
/// or if the end of `src` is before the start.
///
/// # Examples
///
/// Copying four bytes within a slice:
///
/// ```
/// # #![feature(copy_within)]
/// let mut bytes = *b"Hello, World!";
///
/// bytes.copy_within(1..5, 8);
///
/// assert_eq!(&bytes, b"Hello, Wello!");
/// ```
#[unstable(feature = "copy_within", issue = "54236")]
pub fn copy_within<R: ops::RangeBounds<usize>>(&mut self, src: R, dest: usize)
where
T: Copy,
{
let src_start = match src.start_bound() {
ops::Bound::Included(&n) => n,
ops::Bound::Excluded(&n) => n
.checked_add(1)
.unwrap_or_else(|| slice_index_overflow_fail()),
ops::Bound::Unbounded => 0,
};
let src_end = match src.end_bound() {
ops::Bound::Included(&n) => n
.checked_add(1)
.unwrap_or_else(|| slice_index_overflow_fail()),
ops::Bound::Excluded(&n) => n,
ops::Bound::Unbounded => self.len(),
};
assert!(src_start <= src_end, "src end is before src start");
assert!(src_end <= self.len(), "src is out of bounds");
let count = src_end - src_start;
assert!(dest <= self.len() - count, "dest is out of bounds");
unsafe {
ptr::copy(
self.get_unchecked(src_start),
self.get_unchecked_mut(dest),
count,
);
}
}

/// Swaps all elements in `self` with those in `other`.
///
/// The length of `other` must be the same as `self`.
Expand Down

0 comments on commit b3ffd33

Please sign in to comment.