Address comments.
1. Use next_back for last. 2. Use slices for computing nth. It might be possible to use the same code for both the mut/const case but I don't know how that will play with compiler optimizations.
This commit is contained in:
parent
de8c79a535
commit
50c6c6ca90
@ -674,51 +674,13 @@ macro_rules! iterator {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn nth(&mut self, n: usize) -> Option<$elem> {
|
fn nth(&mut self, n: usize) -> Option<$elem> {
|
||||||
// could be implemented with slices, but this avoids bounds checks
|
// Call helper method. Can't put the definition here because mut versus const.
|
||||||
unsafe {
|
self.iter_nth(n)
|
||||||
::intrinsics::assume(!self.ptr.is_null());
|
|
||||||
::intrinsics::assume(!self.end.is_null());
|
|
||||||
// There should be some way to use offset and optimize this to LEA but I don't
|
|
||||||
// know how to do that AND detect overflow...
|
|
||||||
let size = mem::size_of::<T>();
|
|
||||||
if size == 0 {
|
|
||||||
if let Some(new_ptr) = (self.ptr as usize).checked_add(n) {
|
|
||||||
if new_ptr < (self.end as usize) {
|
|
||||||
self.ptr = transmute(new_ptr + 1);
|
|
||||||
return Some(&mut *(1 as *mut _))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let Some(new_ptr) = n.checked_mul(size).and_then(|offset| {
|
|
||||||
(self.ptr as usize).checked_add(offset)
|
|
||||||
}) {
|
|
||||||
if new_ptr < (self.end as usize) {
|
|
||||||
self.ptr = transmute(new_ptr + size);
|
|
||||||
return Some(transmute(new_ptr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn last(self) -> Option<$elem> {
|
fn last(mut self) -> Option<$elem> {
|
||||||
// We could just call next_back but this avoids the memory write.
|
self.next_back()
|
||||||
unsafe {
|
|
||||||
::intrinsics::assume(!self.ptr.is_null());
|
|
||||||
::intrinsics::assume(!self.end.is_null());
|
|
||||||
if self.end == self.ptr {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
if mem::size_of::<T>() == 0 {
|
|
||||||
// Use a non-null pointer value
|
|
||||||
Some(&mut *(1 as *mut _))
|
|
||||||
} else {
|
|
||||||
Some(transmute(self.end.offset(-1)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -839,6 +801,27 @@ impl<'a, T> Iter<'a, T> {
|
|||||||
pub fn as_slice(&self) -> &'a [T] {
|
pub fn as_slice(&self) -> &'a [T] {
|
||||||
make_slice!(T => &'a [T]: self.ptr, self.end)
|
make_slice!(T => &'a [T]: self.ptr, self.end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function for Iter::nth
|
||||||
|
fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
|
||||||
|
match self.as_slice().get(n) {
|
||||||
|
Some(elem_ref) => if mem::size_of::<T>() == 0 {
|
||||||
|
unsafe {
|
||||||
|
self.ptr = transmute((elem_ref as *const _) as usize + 1);
|
||||||
|
Some(& *(1 as *const _))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
self.ptr = (elem_ref as *const _).offset(1);
|
||||||
|
Some(elem_ref)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
self.ptr = self.end;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator!{struct Iter -> *const T, &'a T}
|
iterator!{struct Iter -> *const T, &'a T}
|
||||||
@ -968,6 +951,27 @@ impl<'a, T> IterMut<'a, T> {
|
|||||||
pub fn into_slice(self) -> &'a mut [T] {
|
pub fn into_slice(self) -> &'a mut [T] {
|
||||||
make_mut_slice!(T => &'a mut [T]: self.ptr, self.end)
|
make_mut_slice!(T => &'a mut [T]: self.ptr, self.end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function for IterMut::nth
|
||||||
|
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
|
||||||
|
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
|
||||||
|
Some(elem_ref) => if mem::size_of::<T>() == 0 {
|
||||||
|
unsafe {
|
||||||
|
self.ptr = transmute((elem_ref as *mut _) as usize + 1);
|
||||||
|
Some(&mut *(1 as *mut _))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
self.ptr = (elem_ref as *mut _).offset(1);
|
||||||
|
Some(elem_ref)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
self.ptr = self.end;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator!{struct IterMut -> *mut T, &'a mut T}
|
iterator!{struct IterMut -> *mut T, &'a mut T}
|
||||||
|
Loading…
Reference in New Issue
Block a user