From b3ffd3344e3ac5e2468c7255c2bbecac13daab82 Mon Sep 17 00:00:00 2001 From: Jack O'Connor Date: Thu, 23 Aug 2018 18:22:53 -0400 Subject: [PATCH] define copy_within on slices 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. --- src/libcore/slice/mod.rs | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index da4a56cfecd6..e4ac79a26d86 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1618,6 +1618,63 @@ impl [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>(&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`.