]> git.proxmox.com Git - rustc.git/blob - src/doc/nomicon/vec-insert-remove.md
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / doc / nomicon / vec-insert-remove.md
1 % Insert and Remove
2
3 Something *not* provided by slice is `insert` and `remove`, so let's do those
4 next.
5
6 Insert needs to shift all the elements at the target index to the right by one.
7 To do this we need to use `ptr::copy`, which is our version of C's `memmove`.
8 This copies some chunk of memory from one location to another, correctly
9 handling the case where the source and destination overlap (which will
10 definitely happen here).
11
12 If we insert at index `i`, we want to shift the `[i .. len]` to `[i+1 .. len+1]`
13 using the old len.
14
15 ```rust,ignore
16 pub fn insert(&mut self, index: usize, elem: T) {
17 // Note: `<=` because it's valid to insert after everything
18 // which would be equivalent to push.
19 assert!(index <= self.len, "index out of bounds");
20 if self.cap == self.len { self.grow(); }
21
22 unsafe {
23 if index < self.len {
24 // ptr::copy(src, dest, len): "copy from source to dest len elems"
25 ptr::copy(self.ptr.offset(index as isize),
26 self.ptr.offset(index as isize + 1),
27 len - index);
28 }
29 ptr::write(self.ptr.offset(index as isize), elem);
30 self.len += 1;
31 }
32 }
33 ```
34
35 Remove behaves in the opposite manner. We need to shift all the elements from
36 `[i+1 .. len + 1]` to `[i .. len]` using the *new* len.
37
38 ```rust,ignore
39 pub fn remove(&mut self, index: usize) -> T {
40 // Note: `<` because it's *not* valid to remove after everything
41 assert!(index < self.len, "index out of bounds");
42 unsafe {
43 self.len -= 1;
44 let result = ptr::read(self.ptr.offset(index as isize));
45 ptr::copy(self.ptr.offset(index as isize + 1),
46 self.ptr.offset(index as isize),
47 len - index);
48 result
49 }
50 }
51 ```