| # Insert and Remove | |
| Something *not* provided by slice is `insert` and `remove`, so let's do those | |
| next. | |
| Insert needs to shift all the elements at the target index to the right by one. | |
| To do this we need to use `ptr::copy`, which is our version of C's `memmove`. | |
| This copies some chunk of memory from one location to another, correctly | |
| handling the case where the source and destination overlap (which will | |
| definitely happen here). | |
| If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]` | |
| using the old len. | |
| <!-- ignore: simplified code --> | |
| ```rust,ignore | |
| pub fn insert(&mut self, index: usize, elem: T) { | |
| // Note: `<=` because it's valid to insert after everything | |
| // which would be equivalent to push. | |
| assert!(index <= self.len, "index out of bounds"); | |
| if self.len == self.cap { self.grow(); } | |
| unsafe { | |
| // ptr::copy(src, dest, len): "copy from src to dest len elems" | |
| ptr::copy( | |
| self.ptr.as_ptr().add(index), | |
| self.ptr.as_ptr().add(index + 1), | |
| self.len - index, | |
| ); | |
| ptr::write(self.ptr.as_ptr().add(index), elem); | |
| } | |
| self.len += 1; | |
| } | |
| ``` | |
| Remove behaves in the opposite manner. We need to shift all the elements from | |
| `[i+1 .. len + 1]` to `[i .. len]` using the *new* len. | |
| <!-- ignore: simplified code --> | |
| ```rust,ignore | |
| pub fn remove(&mut self, index: usize) -> T { | |
| // Note: `<` because it's *not* valid to remove after everything | |
| assert!(index < self.len, "index out of bounds"); | |
| unsafe { | |
| self.len -= 1; | |
| let result = ptr::read(self.ptr.as_ptr().add(index)); | |
| ptr::copy( | |
| self.ptr.as_ptr().add(index + 1), | |
| self.ptr.as_ptr().add(index), | |
| self.len - index, | |
| ); | |
| result | |
| } | |
| } | |
| ``` |