Skip to content

Commit e129b92

Browse files
committed
Deduplicate slice iter offset/transmute code.
1 parent 50c6c6c commit e129b92

File tree

1 file changed

+41
-45
lines changed

1 file changed

+41
-45
lines changed

src/libcore/slice.rs

+41-45
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,36 @@ impl<'a, T> IntoIterator for &'a mut [T] {
625625
}
626626
}
627627

628+
#[inline(always)]
629+
fn size_from_ptr<T>(_: *const T) -> usize {
630+
mem::size_of::<T>()
631+
}
632+
633+
634+
// Use macro to be generic over const/mut
635+
macro_rules! slice_offset {
636+
($ptr:expr, $by:expr) => {{
637+
let ptr = $ptr;
638+
if size_from_ptr(ptr) == 0 {
639+
transmute(ptr as usize + $by)
640+
} else {
641+
ptr.offset($by)
642+
}
643+
}};
644+
}
645+
646+
macro_rules! slice_ref {
647+
($ptr:expr) => {{
648+
let ptr = $ptr;
649+
if size_from_ptr(ptr) == 0 {
650+
// Use a non-null pointer value
651+
&mut *(1 as *mut _)
652+
} else {
653+
transmute(ptr)
654+
}
655+
}};
656+
}
657+
628658
// The shared definition of the `Iter` and `IterMut` iterators
629659
macro_rules! iterator {
630660
(struct $name:ident -> $ptr:ty, $elem:ty) => {
@@ -641,20 +671,9 @@ macro_rules! iterator {
641671
if self.ptr == self.end {
642672
None
643673
} else {
644-
if mem::size_of::<T>() == 0 {
645-
// purposefully don't use 'ptr.offset' because for
646-
// vectors with 0-size elements this would return the
647-
// same pointer.
648-
self.ptr = transmute(self.ptr as usize + 1);
649-
650-
// Use a non-null pointer value
651-
Some(&mut *(1 as *mut _))
652-
} else {
653-
let old = self.ptr;
654-
self.ptr = self.ptr.offset(1);
655-
656-
Some(transmute(old))
657-
}
674+
let old = self.ptr;
675+
self.ptr = slice_offset!(self.ptr, 1);
676+
Some(slice_ref!(old))
658677
}
659678
}
660679
}
@@ -695,17 +714,8 @@ macro_rules! iterator {
695714
if self.end == self.ptr {
696715
None
697716
} else {
698-
if mem::size_of::<T>() == 0 {
699-
// See above for why 'ptr.offset' isn't used
700-
self.end = transmute(self.end as usize - 1);
701-
702-
// Use a non-null pointer value
703-
Some(&mut *(1 as *mut _))
704-
} else {
705-
self.end = self.end.offset(-1);
706-
707-
Some(transmute(self.end))
708-
}
717+
self.end = slice_offset!(self.end, -1);
718+
Some(slice_ref!(self.end))
709719
}
710720
}
711721
}
@@ -805,16 +815,9 @@ impl<'a, T> Iter<'a, T> {
805815
// Helper function for Iter::nth
806816
fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
807817
match self.as_slice().get(n) {
808-
Some(elem_ref) => if mem::size_of::<T>() == 0 {
809-
unsafe {
810-
self.ptr = transmute((elem_ref as *const _) as usize + 1);
811-
Some(& *(1 as *const _))
812-
}
813-
} else {
814-
unsafe {
815-
self.ptr = (elem_ref as *const _).offset(1);
816-
Some(elem_ref)
817-
}
818+
Some(elem_ref) => unsafe {
819+
self.ptr = slice_offset!(elem_ref as *const _, 1);
820+
Some(slice_ref!(elem_ref))
818821
},
819822
None => {
820823
self.ptr = self.end;
@@ -955,16 +958,9 @@ impl<'a, T> IterMut<'a, T> {
955958
// Helper function for IterMut::nth
956959
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
957960
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
958-
Some(elem_ref) => if mem::size_of::<T>() == 0 {
959-
unsafe {
960-
self.ptr = transmute((elem_ref as *mut _) as usize + 1);
961-
Some(&mut *(1 as *mut _))
962-
}
963-
} else {
964-
unsafe {
965-
self.ptr = (elem_ref as *mut _).offset(1);
966-
Some(elem_ref)
967-
}
961+
Some(elem_ref) => unsafe {
962+
self.ptr = slice_offset!(elem_ref as *mut _, 1);
963+
Some(slice_ref!(elem_ref))
968964
},
969965
None => {
970966
self.ptr = self.end;

0 commit comments

Comments
 (0)