| # 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 |
| } |
| } |
| ``` |