插入和删除

切片 *没有* 提供的东西是 insertremove,所以我们接下来处理它们。

插入需要在目标索引处将所有元素向右移动一位。为此,我们需要使用 ptr::copy,它是我们版本的 C 的 memmove。这会将一些内存块从一个位置复制到另一个位置,正确处理源和目标重叠的情况(这种情况肯定会发生)。

如果我们在索引 i 处插入,我们希望使用旧的 len 将 [i .. len] 移动到 [i+1 .. len+1]

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;
}

删除的行为方式相反。我们需要使用*新*的 len 将所有元素从 [i+1 .. len + 1] 移动到 [i .. len]

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