Skip to content

Commit c1db77e

Browse files
committed
core: Convert utility macros for the slice iterator into a trait
Use an extension trait for the slice iterator's pointer manipulations.
1 parent 127a83d commit c1db77e

File tree

1 file changed

+57
-11
lines changed

1 file changed

+57
-11
lines changed

src/libcore/slice.rs

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,21 +161,35 @@ macro_rules! slice_offset {
161161
($ptr:expr, $by:expr) => {{
162162
let ptr = $ptr;
163163
if size_from_ptr(ptr) == 0 {
164-
::intrinsics::arith_offset(ptr as *mut i8, $by) as *mut _
164+
(ptr as *mut i8).wrapping_offset($by) as _
165165
} else {
166166
ptr.offset($by)
167167
}
168168
}};
169169
}
170170

171-
macro_rules! slice_ref {
171+
// make a &T from a *const T
172+
macro_rules! make_ref {
173+
($ptr:expr) => {{
174+
let ptr = $ptr;
175+
if size_from_ptr(ptr) == 0 {
176+
// Use a non-null pointer value
177+
&*(1 as *mut _)
178+
} else {
179+
&*ptr
180+
}
181+
}};
182+
}
183+
184+
// make a &mut T from a *mut T
185+
macro_rules! make_ref_mut {
172186
($ptr:expr) => {{
173187
let ptr = $ptr;
174188
if size_from_ptr(ptr) == 0 {
175189
// Use a non-null pointer value
176190
&mut *(1 as *mut _)
177191
} else {
178-
mem::transmute(ptr)
192+
&mut *ptr
179193
}
180194
}};
181195
}
@@ -796,7 +810,7 @@ fn size_from_ptr<T>(_: *const T) -> usize {
796810

797811
// The shared definition of the `Iter` and `IterMut` iterators
798812
macro_rules! iterator {
799-
(struct $name:ident -> $ptr:ty, $elem:ty) => {
813+
(struct $name:ident -> $ptr:ty, $elem:ty, $mkref:ident) => {
800814
#[stable(feature = "rust1", since = "1.0.0")]
801815
impl<'a, T> Iterator for $name<'a, T> {
802816
type Item = $elem;
@@ -812,9 +826,7 @@ macro_rules! iterator {
812826
if self.ptr == self.end {
813827
None
814828
} else {
815-
let old = self.ptr;
816-
self.ptr = slice_offset!(self.ptr, 1);
817-
Some(slice_ref!(old))
829+
Some($mkref!(self.ptr.post_inc()))
818830
}
819831
}
820832
}
@@ -857,8 +869,7 @@ macro_rules! iterator {
857869
if self.end == self.ptr {
858870
None
859871
} else {
860-
self.end = slice_offset!(self.end, -1);
861-
Some(slice_ref!(self.end))
872+
Some($mkref!(self.end.pre_dec()))
862873
}
863874
}
864875
}
@@ -980,7 +991,7 @@ impl<'a, T> Iter<'a, T> {
980991
}
981992
}
982993

983-
iterator!{struct Iter -> *const T, &'a T}
994+
iterator!{struct Iter -> *const T, &'a T, make_ref}
984995

985996
#[stable(feature = "rust1", since = "1.0.0")]
986997
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
@@ -1104,7 +1115,7 @@ impl<'a, T> IterMut<'a, T> {
11041115
}
11051116
}
11061117

1107-
iterator!{struct IterMut -> *mut T, &'a mut T}
1118+
iterator!{struct IterMut -> *mut T, &'a mut T, make_ref_mut}
11081119

11091120
#[stable(feature = "rust1", since = "1.0.0")]
11101121
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
@@ -1115,6 +1126,41 @@ impl<'a, T> FusedIterator for IterMut<'a, T> {}
11151126
#[unstable(feature = "trusted_len", issue = "37572")]
11161127
unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
11171128

1129+
1130+
// Extension methods for raw pointers, used by the iterators
1131+
trait PointerExt : Copy {
1132+
unsafe fn slice_offset(self, i: isize) -> Self;
1133+
1134+
/// Increment self by 1, but return the old value
1135+
#[inline(always)]
1136+
unsafe fn post_inc(&mut self) -> Self {
1137+
let current = *self;
1138+
*self = self.slice_offset(1);
1139+
current
1140+
}
1141+
1142+
/// Decrement self by 1, and return the new value
1143+
#[inline(always)]
1144+
unsafe fn pre_dec(&mut self) -> Self {
1145+
*self = self.slice_offset(-1);
1146+
*self
1147+
}
1148+
}
1149+
1150+
impl<T> PointerExt for *const T {
1151+
#[inline(always)]
1152+
unsafe fn slice_offset(self, i: isize) -> Self {
1153+
slice_offset!(self, i)
1154+
}
1155+
}
1156+
1157+
impl<T> PointerExt for *mut T {
1158+
#[inline(always)]
1159+
unsafe fn slice_offset(self, i: isize) -> Self {
1160+
slice_offset!(self, i)
1161+
}
1162+
}
1163+
11181164
/// An internal abstraction over the splitting iterators, so that
11191165
/// splitn, splitn_mut etc can be implemented once.
11201166
#[doc(hidden)]

0 commit comments

Comments
 (0)