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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
//! This crate contains a single function `moveslice`. Its purpose //! is to move a chunk within a slice around. It only uses safe functions, //! and acts efficiently by using the //! [`split_at_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at_mut) //! and //! [`rotate_left`](https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_left)/ //! [`rotate_right`](https://doc.rust-lang.org/std/primitive.slice.html#method.rotate_right) //! functions. //! //! # Examples: //! //! ``` //! use moveslice::moveslice; //! //! let mut arr = [1,2,3,4,5,6,7,8,9]; //! //! // The following moves the slice 3..6 to index 1. //! // In effect, it moves [4,5,6] over to where [2] is. //! moveslice(&mut arr, (3,6), 1); //! assert_eq!(arr, [1,4,5,6,2,3,7,8,9]); //! //! // The following moves the slice 3..6 to index 6. //! // In effect, it moves [6,2,3] over to where [7] is. //! moveslice(&mut arr, (3,6), 6); //! assert_eq!(arr, [1,4,5,7,8,9,6,2,3]); //! //! // The following attempts to move the slice beyond boundaries. //! // The index given is 7, which exists in the array, but the //! // last element of the chunk will not fit (7 + 3 = 10 > 9). //! // Therefore, the following should fail. //! # #[should_panic] //! # fn main() { //! # let mut arr = [1,2,3,4,5,6,7,8,9]; //! let result = moveslice(&mut arr, (3,6), 7); //! # } //! //! // You could pass the destination as the same value as chunk.0. //! // However this would mean nothing is moved. //! // Since it's not technically an error however, only a warning is logged. //! moveslice(&mut arr, (0,3), 0); //! ``` /// Moves a slice around in an array. /// Works by splitting and rotating. /// /// There are three parameters: /// /// - `slice` : The slice to modify. /// - `chunk` : A tuple with the boundaries of the chunk you want to move. /// - `destination` : Where you want to move the chunk. /// /// Note that the destination specifies where the *first* element of the chunk /// will be. As a result, its maximum value is not the length of the slice. /// /// For example, if you have a slice with size 10, and you're moving a chunk of /// size 3 around, the maximum value for the destination is *10-3=* ***7***. /// /// # Panics /// Panics when the destination leads the chunk out of bounds. /// /// In the example above, if I specify a destination of 8, the function will panic, /// showing what would be the placement of the chunk, and the length of the slice. /// /// ```should_panic /// # use moveslice::moveslice; /// # fn main() { /// let mut arr = [1,2,3,4,5,6,7,8,9]; /// let result = moveslice(&mut arr, (3,6), 7); // will panic /// # } /// ``` pub fn moveslice<T>(slice: &mut [T], chunk: (usize, usize), destination: usize) { if destination > chunk.0 { let len = { slice.len() }; let index1 = chunk.0; let index2 = destination; let chunksize = chunk.1 - chunk.0; let (_, mid) = slice.split_at_mut(index1); let mid = if destination + chunksize <= len { mid.split_at_mut(index2).0 } else { panic!("Direction goes beyond slice [len = {}, destination = {}..{}]. ", len, destination, destination + chunksize); }; mid.rotate_left(chunk.1-chunk.0); } else if destination < chunk.0 { let index1 = destination; let index2 = chunk.1 - destination; let (_, mid) = slice.split_at_mut(index1); let mid = mid.split_at_mut(index2).0; mid.rotate_right(chunk.1-chunk.0); } else { println!("The destination is the same as the start of the chunk. Nothing was moved."); } }