Minor improvements to Vec (#415)

pull/438/head
Eva Pace 10 months ago committed by GitHub
parent 360a768c6d
commit f6bd083c4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -93,7 +93,7 @@ impl<T> IntoIterator for Vec<T> {
mem::forget(self); mem::forget(self);
IntoIter { IntoIter {
iter: iter, iter,
_buf: buf, _buf: buf,
} }
} }
@ -135,18 +135,16 @@ impl<'a, T> Drop for Drain<'a, T> {
impl<T> Vec<T> { impl<T> Vec<T> {
pub fn drain(&mut self) -> Drain<T> { pub fn drain(&mut self) -> Drain<T> {
unsafe { let iter = unsafe { RawValIter::new(&self) };
let iter = RawValIter::new(&self);
// this is a mem::forget safety thing. If Drain is forgotten, we just // this is a mem::forget safety thing. If Drain is forgotten, we just
// leak the whole Vec's contents. Also we need to do this *eventually* // leak the whole Vec's contents. Also we need to do this *eventually*
// anyway, so why not do it now? // anyway, so why not do it now?
self.len = 0; self.len = 0;
Drain { Drain {
iter: iter, iter,
vec: PhantomData, vec: PhantomData,
}
} }
} }
} }

@ -127,7 +127,7 @@ impl<T> Vec<T> {
pub fn insert(&mut self, index: usize, elem: T) { pub fn insert(&mut self, index: usize, elem: T) {
assert!(index <= self.len, "index out of bounds"); assert!(index <= self.len, "index out of bounds");
if self.cap() == self.len { if self.len == self.cap() {
self.buf.grow(); self.buf.grow();
} }
@ -138,14 +138,17 @@ impl<T> Vec<T> {
self.len - index, self.len - index,
); );
ptr::write(self.ptr().add(index), elem); ptr::write(self.ptr().add(index), elem);
self.len += 1;
} }
self.len += 1;
} }
pub fn remove(&mut self, index: usize) -> T { pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len, "index out of bounds"); assert!(index < self.len, "index out of bounds");
self.len -= 1;
unsafe { unsafe {
self.len -= 1;
let result = ptr::read(self.ptr().add(index)); let result = ptr::read(self.ptr().add(index));
ptr::copy( ptr::copy(
self.ptr().add(index + 1), self.ptr().add(index + 1),
@ -157,18 +160,16 @@ impl<T> Vec<T> {
} }
pub fn drain(&mut self) -> Drain<T> { pub fn drain(&mut self) -> Drain<T> {
unsafe { let iter = unsafe { RawValIter::new(&self) };
let iter = RawValIter::new(&self);
// this is a mem::forget safety thing. If Drain is forgotten, we just // this is a mem::forget safety thing. If Drain is forgotten, we just
// leak the whole Vec's contents. Also we need to do this *eventually* // leak the whole Vec's contents. Also we need to do this *eventually*
// anyway, so why not do it now? // anyway, so why not do it now?
self.len = 0; self.len = 0;
Drain { Drain {
iter: iter, iter,
vec: PhantomData, vec: PhantomData,
}
} }
} }
} }
@ -197,15 +198,15 @@ impl<T> IntoIterator for Vec<T> {
type Item = T; type Item = T;
type IntoIter = IntoIter<T>; type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> { fn into_iter(self) -> IntoIter<T> {
unsafe { let (iter, buf) = unsafe {
let iter = RawValIter::new(&self); (RawValIter::new(&self), ptr::read(&self.buf))
let buf = ptr::read(&self.buf); };
mem::forget(self);
IntoIter { mem::forget(self);
iter: iter,
_buf: buf, IntoIter {
} iter,
_buf: buf,
} }
} }
} }

@ -18,7 +18,7 @@ pub fn insert(&mut self, index: usize, elem: T) {
// Note: `<=` because it's valid to insert after everything // Note: `<=` because it's valid to insert after everything
// which would be equivalent to push. // which would be equivalent to push.
assert!(index <= self.len, "index out of bounds"); assert!(index <= self.len, "index out of bounds");
if self.cap == self.len { self.grow(); } if self.len == self.cap { self.grow(); }
unsafe { unsafe {
// ptr::copy(src, dest, len): "copy from src to dest len elems" // ptr::copy(src, dest, len): "copy from src to dest len elems"
@ -28,8 +28,9 @@ pub fn insert(&mut self, index: usize, elem: T) {
self.len - index, self.len - index,
); );
ptr::write(self.ptr.as_ptr().add(index), elem); ptr::write(self.ptr.as_ptr().add(index), elem);
self.len += 1;
} }
self.len += 1;
} }
``` ```

@ -68,18 +68,16 @@ impl<T> IntoIterator for Vec<T> {
let cap = vec.cap; let cap = vec.cap;
let len = vec.len; let len = vec.len;
unsafe { IntoIter {
IntoIter { buf: ptr,
buf: ptr, cap,
cap: cap, start: ptr.as_ptr(),
start: ptr.as_ptr(), end: if cap == 0 {
end: if cap == 0 { // can't offset off this pointer, it's not allocated!
// can't offset off this pointer, it's not allocated! ptr.as_ptr()
ptr.as_ptr() } else {
} else { unsafe { ptr.as_ptr().add(len) }
ptr.as_ptr().add(len) },
},
}
} }
} }
} }

@ -40,7 +40,6 @@ we get the same results as using `Unique<T>`:
```rust ```rust
use std::ptr::NonNull; use std::ptr::NonNull;
use std::marker::PhantomData;
pub struct Vec<T> { pub struct Vec<T> {
ptr: NonNull<T>, ptr: NonNull<T>,

@ -131,23 +131,21 @@ impl<T> IntoIterator for Vec<T> {
type Item = T; type Item = T;
type IntoIter = IntoIter<T>; type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> { fn into_iter(self) -> IntoIter<T> {
unsafe { // need to use ptr::read to unsafely move the buf out since it's
// need to use ptr::read to unsafely move the buf out since it's // not Copy, and Vec implements Drop (so we can't destructure it).
// not Copy, and Vec implements Drop (so we can't destructure it). let buf = unsafe { ptr::read(&self.buf) };
let buf = ptr::read(&self.buf); let len = self.len;
let len = self.len; mem::forget(self);
mem::forget(self);
IntoIter {
IntoIter { start: buf.ptr.as_ptr(),
start: buf.ptr.as_ptr(), end: if buf.cap == 0 {
end: if buf.cap == 0 { // can't offset off of a pointer unless it's part of an allocation
// can't offset off of a pointer unless it's part of an allocation buf.ptr.as_ptr()
buf.ptr.as_ptr() } else {
} else { unsafe { buf.ptr.as_ptr().add(len) }
buf.ptr.as_ptr().add(len) },
}, _buf: buf,
_buf: buf,
}
} }
} }
} }

Loading…
Cancel
Save