#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn swap(&mut self, a: usize, b: usize) {
- // Can't take two mutable loans from one vector, so instead use raw pointers.
- let pa = ptr::addr_of_mut!(self[a]);
- let pb = ptr::addr_of_mut!(self[b]);
- // SAFETY: `pa` and `pb` have been created from safe mutable references and refer
- // to elements in the slice and therefore are guaranteed to be valid and aligned.
- // Note that accessing the elements behind `a` and `b` is checked and will
- // panic when out of bounds.
+ let _ = &self[a];
+ let _ = &self[b];
+
+ // SAFETY: we just checked that both `a` and `b` are in bounds
+ unsafe { self.swap_unchecked(a, b) }
+ }
+
+ /// Swaps two elements in the slice, without doing bounds checking.
+ ///
+ /// For a safe alternative see [`swap`].
+ ///
+ /// # Arguments
+ ///
+ /// * a - The index of the first element
+ /// * b - The index of the second element
+ ///
+ /// # Safety
+ ///
+ /// Calling this method with an out-of-bounds index is *[undefined behavior]*.
+ /// The caller has to ensure that `a < self.len()` and `b < self.len()`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_swap_unchecked)]
+ ///
+ /// let mut v = ["a", "b", "c", "d"];
+ /// // SAFETY: we know that 1 and 3 are both indices of the slice
+ /// unsafe { v.swap_unchecked(1, 3) };
+ /// assert!(v == ["a", "d", "c", "b"]);
+ /// ```
+ ///
+ /// [`swap`]: slice::swap
+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ #[unstable(feature = "slice_swap_unchecked", issue = "88539")]
+ pub unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
+ #[cfg(debug_assertions)]
+ {
+ let _ = &self[a];
+ let _ = &self[b];
+ }
+
+ let ptr = self.as_mut_ptr();
+ // SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()`
unsafe {
- ptr::swap(pa, pb);
+ ptr::swap(ptr.add(a), ptr.add(b));
}
}
// The resulting pointers `pa` and `pb` are therefore valid and
// aligned, and can be read from and written to.
unsafe {
- // Unsafe swap to avoid the bounds check in safe swap.
- let ptr = self.as_mut_ptr();
- let pa = ptr.add(i);
- let pb = ptr.add(ln - i - 1);
- ptr::swap(pa, pb);
+ self.swap_unchecked(i, ln - i - 1);
}
i += 1;
}
unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) }
}
+ /// Divides one slice into an array and a remainder slice at an index.
+ ///
+ /// The array will contain all indices from `[0, N)` (excluding
+ /// the index `N` itself) and the slice will contain all
+ /// indices from `[N, len)` (excluding the index `len` itself).
+ ///
+ /// # Panics
+ ///
+ /// Panics if `N > len`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(split_array)]
+ ///
+ /// let v = &[1, 2, 3, 4, 5, 6][..];
+ ///
+ /// {
+ /// let (left, right) = v.split_array_ref::<0>();
+ /// assert_eq!(left, &[]);
+ /// assert_eq!(right, [1, 2, 3, 4, 5, 6]);
+ /// }
+ ///
+ /// {
+ /// let (left, right) = v.split_array_ref::<2>();
+ /// assert_eq!(left, &[1, 2]);
+ /// assert_eq!(right, [3, 4, 5, 6]);
+ /// }
+ ///
+ /// {
+ /// let (left, right) = v.split_array_ref::<6>();
+ /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
+ /// assert_eq!(right, []);
+ /// }
+ /// ```
+ #[unstable(feature = "split_array", reason = "new API", issue = "90091")]
+ #[inline]
+ pub fn split_array_ref<const N: usize>(&self) -> (&[T; N], &[T]) {
+ let (a, b) = self.split_at(N);
+ // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at)
+ unsafe { (&*(a.as_ptr() as *const [T; N]), b) }
+ }
+
+ /// Divides one mutable slice into an array and a remainder slice at an index.
+ ///
+ /// The array will contain all indices from `[0, N)` (excluding
+ /// the index `N` itself) and the slice will contain all
+ /// indices from `[N, len)` (excluding the index `len` itself).
+ ///
+ /// # Panics
+ ///
+ /// Panics if `N > len`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(split_array)]
+ ///
+ /// let mut v = &mut [1, 0, 3, 0, 5, 6][..];
+ /// let (left, right) = v.split_array_mut::<2>();
+ /// assert_eq!(left, &mut [1, 0]);
+ /// assert_eq!(right, [3, 0, 5, 6]);
+ /// left[1] = 2;
+ /// right[1] = 4;
+ /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
+ /// ```
+ #[unstable(feature = "split_array", reason = "new API", issue = "90091")]
+ #[inline]
+ pub fn split_array_mut<const N: usize>(&mut self) -> (&mut [T; N], &mut [T]) {
+ let (a, b) = self.split_at_mut(N);
+ // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
+ unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) }
+ }
+
/// Returns an iterator over subslices separated by elements that match
/// `pred`. The matched element is not contained in the subslices.
///
///
/// The length of `src` must be the same as `self`.
///
- /// If `T` implements `Copy`, it can be more performant to use
- /// [`copy_from_slice`].
- ///
/// # Panics
///
/// This function will panic if the two slices have different lengths.