1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
//! [Repo](https://github.com/oconnor663/copy_in_place) — //! [Docs](https://docs.rs/copy_in_place) — //! [Crate](https://crates.io/crates/copy_in_place) //! //! This crate provides a single function, a safe wrapper around [`ptr::copy`] //! for efficient copying within slices. The goal is to eventually include this //! as a built-in method on slices in libcore ([PR #53652]). //! //! # Examples //! //! Copying four bytes within a slice: //! //! ``` //! # use copy_in_place::copy_in_place; //! let mut bytes = *b"Hello, World!"; //! //! copy_in_place(&mut bytes, 1..5, 8); //! //! assert_eq!(&bytes, b"Hello, Wello!"); //! ``` //! //! [`ptr::copy`]: https://doc.rust-lang.org/std/ptr/fn.copy.html //! [PR #53652]: https://github.com/rust-lang/rust/pull/53652 #![no_std] use core::ops::Bound; use core::ops::RangeBounds; /// Copies elements from one part of a slice to another part of the same /// slice, using a memmove. /// /// `src` is the range within the slice to copy from. `dest` is the starting /// index of the range within the slice 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 `slice.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: /// /// ``` /// # use copy_in_place::copy_in_place; /// let mut bytes = *b"Hello, World!"; /// /// copy_in_place(&mut bytes, 1..5, 8); /// /// assert_eq!(&bytes, b"Hello, Wello!"); /// ``` pub fn copy_in_place<T: Copy, R: RangeBounds<usize>>(slice: &mut [T], src: R, dest: usize) { let src_start = match src.start_bound() { Bound::Included(&n) => n, Bound::Excluded(&n) => n.checked_add(1).expect("range bound overflows usize"), Bound::Unbounded => 0, }; let src_end = match src.end_bound() { Bound::Included(&n) => n.checked_add(1).expect("range bound overflows usize"), Bound::Excluded(&n) => n, Bound::Unbounded => slice.len(), }; assert!(src_start <= src_end, "src end is before src start"); assert!(src_end <= slice.len(), "src is out of bounds"); let count = src_end - src_start; assert!(dest <= slice.len() - count, "dest is out of bounds"); unsafe { core::ptr::copy( slice.get_unchecked(src_start), slice.get_unchecked_mut(dest), count, ); } }