1
Fork 0

core: Convert utility macros for the slice iterator into a trait

Use an extension trait for the slice iterator's pointer manipulations.
This commit is contained in:
Ulrik Sverdrup 2016-11-23 23:02:30 +01:00
parent 127a83df66
commit c1db77e9b9

View file

@ -161,21 +161,35 @@ macro_rules! slice_offset {
($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
::intrinsics::arith_offset(ptr as *mut i8, $by) as *mut _
(ptr as *mut i8).wrapping_offset($by) as _
} else {
ptr.offset($by)
}
}};
}
macro_rules! slice_ref {
// make a &T from a *const T
macro_rules! make_ref {
($ptr:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
// Use a non-null pointer value
&*(1 as *mut _)
} else {
&*ptr
}
}};
}
// make a &mut T from a *mut T
macro_rules! make_ref_mut {
($ptr:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
// Use a non-null pointer value
&mut *(1 as *mut _)
} else {
mem::transmute(ptr)
&mut *ptr
}
}};
}
@ -796,7 +810,7 @@ fn size_from_ptr<T>(_: *const T) -> usize {
// The shared definition of the `Iter` and `IterMut` iterators
macro_rules! iterator {
(struct $name:ident -> $ptr:ty, $elem:ty) => {
(struct $name:ident -> $ptr:ty, $elem:ty, $mkref:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Iterator for $name<'a, T> {
type Item = $elem;
@ -812,9 +826,7 @@ macro_rules! iterator {
if self.ptr == self.end {
None
} else {
let old = self.ptr;
self.ptr = slice_offset!(self.ptr, 1);
Some(slice_ref!(old))
Some($mkref!(self.ptr.post_inc()))
}
}
}
@ -857,8 +869,7 @@ macro_rules! iterator {
if self.end == self.ptr {
None
} else {
self.end = slice_offset!(self.end, -1);
Some(slice_ref!(self.end))
Some($mkref!(self.end.pre_dec()))
}
}
}
@ -980,7 +991,7 @@ impl<'a, T> Iter<'a, T> {
}
}
iterator!{struct Iter -> *const T, &'a T}
iterator!{struct Iter -> *const T, &'a T, make_ref}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
@ -1104,7 +1115,7 @@ impl<'a, T> IterMut<'a, T> {
}
}
iterator!{struct IterMut -> *mut T, &'a mut T}
iterator!{struct IterMut -> *mut T, &'a mut T, make_ref_mut}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
@ -1115,6 +1126,41 @@ impl<'a, T> FusedIterator for IterMut<'a, T> {}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
// Extension methods for raw pointers, used by the iterators
trait PointerExt : Copy {
unsafe fn slice_offset(self, i: isize) -> Self;
/// Increment self by 1, but return the old value
#[inline(always)]
unsafe fn post_inc(&mut self) -> Self {
let current = *self;
*self = self.slice_offset(1);
current
}
/// Decrement self by 1, and return the new value
#[inline(always)]
unsafe fn pre_dec(&mut self) -> Self {
*self = self.slice_offset(-1);
*self
}
}
impl<T> PointerExt for *const T {
#[inline(always)]
unsafe fn slice_offset(self, i: isize) -> Self {
slice_offset!(self, i)
}
}
impl<T> PointerExt for *mut T {
#[inline(always)]
unsafe fn slice_offset(self, i: isize) -> Self {
slice_offset!(self, i)
}
}
/// An internal abstraction over the splitting iterators, so that
/// splitn, splitn_mut etc can be implemented once.
#[doc(hidden)]