Skip to content

Commit 1c55a73

Browse files
committed
Implement it with only safe code
1 parent a891f6e commit 1c55a73

File tree

3 files changed

+128
-163
lines changed

3 files changed

+128
-163
lines changed

library/alloc/tests/slice.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,24 +1904,43 @@ fn test_group_by() {
19041904
let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
19051905

19061906
let mut iter = slice.group_by(|a, b| a == b);
1907-
19081907
assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
1909-
1910-
assert_eq!(iter.remaining(), &[3, 3, 2, 2, 2]);
1911-
19121908
assert_eq!(iter.next(), Some(&[3, 3][..]));
19131909
assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
19141910
assert_eq!(iter.next(), None);
1915-
}
1916-
1917-
#[test]
1918-
fn test_group_by_rev() {
1919-
let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
19201911

19211912
let mut iter = slice.group_by(|a, b| a == b);
1922-
19231913
assert_eq!(iter.next_back(), Some(&[2, 2, 2][..]));
19241914
assert_eq!(iter.next_back(), Some(&[3, 3][..]));
19251915
assert_eq!(iter.next_back(), Some(&[1, 1, 1][..]));
19261916
assert_eq!(iter.next_back(), None);
1917+
1918+
let mut iter = slice.group_by(|a, b| a == b);
1919+
assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
1920+
assert_eq!(iter.next_back(), Some(&[2, 2, 2][..]));
1921+
assert_eq!(iter.next(), Some(&[3, 3][..]));
1922+
assert_eq!(iter.next_back(), None);
1923+
}
1924+
1925+
#[test]
1926+
fn test_group_by_mut() {
1927+
let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2];
1928+
1929+
let mut iter = slice.group_by_mut(|a, b| a == b);
1930+
assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
1931+
assert_eq!(iter.next(), Some(&mut [3, 3][..]));
1932+
assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
1933+
assert_eq!(iter.next(), None);
1934+
1935+
let mut iter = slice.group_by_mut(|a, b| a == b);
1936+
assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..]));
1937+
assert_eq!(iter.next_back(), Some(&mut [3, 3][..]));
1938+
assert_eq!(iter.next_back(), Some(&mut [1, 1, 1][..]));
1939+
assert_eq!(iter.next_back(), None);
1940+
1941+
let mut iter = slice.group_by_mut(|a, b| a == b);
1942+
assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
1943+
assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..]));
1944+
assert_eq!(iter.next(), Some(&mut [3, 3][..]));
1945+
assert_eq!(iter.next_back(), None);
19271946
}

library/core/src/slice/iter.rs

Lines changed: 97 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -2968,127 +2968,6 @@ unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {
29682968
}
29692969
}
29702970

2971-
macro_rules! group_by {
2972-
(struct $name:ident, $elem:ty, $mkslice:ident) => {
2973-
#[unstable(feature = "slice_group_by", issue = "0")]
2974-
impl<'a, T: 'a, P> $name<'a, T, P> {
2975-
#[inline]
2976-
fn is_empty(&self) -> bool {
2977-
self.ptr == self.end
2978-
}
2979-
2980-
#[inline]
2981-
fn remaining_len(&self) -> usize {
2982-
unsafe { self.end.offset_from(self.ptr) as usize }
2983-
}
2984-
}
2985-
2986-
#[unstable(feature = "slice_group_by", issue = "0")]
2987-
impl<'a, T: 'a, P> Iterator for $name<'a, T, P>
2988-
where P: FnMut(&T, &T) -> bool,
2989-
{
2990-
type Item = $elem;
2991-
2992-
fn next(&mut self) -> Option<Self::Item> {
2993-
// we use an unsafe block to avoid bounds checking here.
2994-
// this is safe because the only thing we do here is to get
2995-
// two elements at `ptr` and `ptr + 1`, bounds checking is done by hand.
2996-
unsafe {
2997-
if self.is_empty() { return None }
2998-
2999-
let mut i = 0;
3000-
let mut ptr = self.ptr;
3001-
3002-
// we need to get *two* contiguous elements so we check that:
3003-
// - the first element is at the `end - 1` position because
3004-
// - the second one will be read from `ptr + 1` that must
3005-
// be lower or equal to `end`
3006-
while ptr != self.end.sub(1) {
3007-
let a = &*ptr;
3008-
ptr = ptr.add(1);
3009-
let b = &*ptr;
3010-
3011-
i += 1;
3012-
3013-
if !(self.predicate)(a, b) {
3014-
let slice = $mkslice(self.ptr, i);
3015-
self.ptr = ptr;
3016-
return Some(slice)
3017-
}
3018-
}
3019-
3020-
// `i` is either `0` or the slice `length - 1` because either:
3021-
// - we have not entered the loop and so `i` is equal to `0`
3022-
// the slice length is necessarily `1` because we ensure it is not empty
3023-
// - we have entered the loop and we have not early returned
3024-
// so `i` is equal to the slice `length - 1`
3025-
let slice = $mkslice(self.ptr, i + 1);
3026-
self.ptr = self.end;
3027-
Some(slice)
3028-
}
3029-
}
3030-
3031-
fn size_hint(&self) -> (usize, Option<usize>) {
3032-
if self.is_empty() { return (0, Some(0)) }
3033-
let len = self.remaining_len();
3034-
(1, Some(len))
3035-
}
3036-
3037-
fn last(mut self) -> Option<Self::Item> {
3038-
self.next_back()
3039-
}
3040-
}
3041-
3042-
#[unstable(feature = "slice_group_by", issue = "0")]
3043-
impl<'a, T: 'a, P> DoubleEndedIterator for $name<'a, T, P>
3044-
where P: FnMut(&T, &T) -> bool,
3045-
{
3046-
fn next_back(&mut self) -> Option<Self::Item> {
3047-
// during the loop we retrieve two elements at `ptr` and `ptr - 1`.
3048-
unsafe {
3049-
if self.is_empty() { return None }
3050-
3051-
let mut i = 0;
3052-
// we ensure that the first element that will be read
3053-
// is not under `end` because `end` is out of bound.
3054-
let mut ptr = self.end.sub(1);
3055-
3056-
while ptr != self.ptr {
3057-
// we first get `a` that is at the left of `ptr`
3058-
// then `b` that is under the `ptr` position.
3059-
let a = &*ptr.sub(1);
3060-
let b = &*ptr;
3061-
3062-
i += 1;
3063-
3064-
if !(self.predicate)(a, b) {
3065-
// the slice to return starts at the `ptr` position
3066-
// and `i` is the length of it.
3067-
let slice = $mkslice(ptr, i);
3068-
3069-
// because `end` is always an invalid bound
3070-
// we use `ptr` as `end` for the future call to `next`.
3071-
self.end = ptr;
3072-
return Some(slice)
3073-
}
3074-
3075-
ptr = ptr.sub(1);
3076-
}
3077-
3078-
let slice = $mkslice(self.ptr, i + 1);
3079-
self.ptr = self.end;
3080-
Some(slice)
3081-
}
3082-
}
3083-
}
3084-
3085-
#[unstable(feature = "slice_group_by", issue = "0")]
3086-
impl<'a, T: 'a, P> FusedIterator for $name<'a, T, P>
3087-
where P: FnMut(&T, &T) -> bool,
3088-
{ }
3089-
}
3090-
}
3091-
30922971
/// An iterator over slice in (non-overlapping) chunks separated by a predicate.
30932972
///
30942973
/// This struct is created by the [`group_by`] method on [slices].
@@ -3098,25 +2977,65 @@ macro_rules! group_by {
30982977
#[unstable(feature = "slice_group_by", issue = "0")]
30992978
#[derive(Debug)] // FIXME implement Debug to be more user friendly
31002979
pub struct GroupBy<'a, T: 'a, P> {
3101-
ptr: *const T,
3102-
end: *const T,
2980+
slice: &'a [T],
31032981
predicate: P,
3104-
_phantom: marker::PhantomData<&'a T>,
31052982
}
31062983

31072984
#[unstable(feature = "slice_group_by", issue = "0")]
3108-
impl<'a, T: 'a, P> GroupBy<'a, T, P>
2985+
impl<'a, T: 'a, P> GroupBy<'a, T, P> {
2986+
pub(super) fn new(slice: &'a [T], predicate: P) -> Self {
2987+
GroupBy { slice, predicate }
2988+
}
2989+
}
2990+
2991+
#[unstable(feature = "slice_group_by", issue = "0")]
2992+
impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P>
31092993
where P: FnMut(&T, &T) -> bool,
31102994
{
3111-
/// Returns the remainder of the original slice that is going to be
3112-
/// returned by the iterator.
3113-
pub fn remaining(&self) -> &[T] {
3114-
let len = self.remaining_len();
3115-
unsafe { from_raw_parts(self.ptr, len) }
2995+
type Item = &'a [T];
2996+
2997+
#[inline]
2998+
fn next(&mut self) -> Option<Self::Item> {
2999+
if self.slice.is_empty() {
3000+
None
3001+
} else {
3002+
let mut len = 1;
3003+
let mut iter = self.slice.windows(2);
3004+
while let Some([l, r]) = iter.next() {
3005+
if (self.predicate)(l, r) { len += 1 } else { break }
3006+
}
3007+
let (head, tail) = self.slice.split_at(len);
3008+
self.slice = tail;
3009+
Some(head)
3010+
}
31163011
}
31173012
}
31183013

3119-
group_by!{ struct GroupBy, &'a [T], from_raw_parts }
3014+
#[unstable(feature = "slice_group_by", issue = "0")]
3015+
impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P>
3016+
where P: FnMut(&T, &T) -> bool,
3017+
{
3018+
#[inline]
3019+
fn next_back(&mut self) -> Option<Self::Item> {
3020+
if self.slice.is_empty() {
3021+
None
3022+
} else {
3023+
let mut len = 1;
3024+
let mut iter = self.slice.windows(2);
3025+
while let Some([l, r]) = iter.next_back() {
3026+
if (self.predicate)(l, r) { len += 1 } else { break }
3027+
}
3028+
let (head, tail) = self.slice.split_at(self.slice.len() - len);
3029+
self.slice = head;
3030+
Some(tail)
3031+
}
3032+
}
3033+
}
3034+
3035+
#[unstable(feature = "slice_group_by", issue = "0")]
3036+
impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P>
3037+
where P: FnMut(&T, &T) -> bool,
3038+
{ }
31203039

31213040
/// An iterator over slice in (non-overlapping) mutable chunks separated
31223041
/// by a predicate.
@@ -3128,22 +3047,59 @@ group_by!{ struct GroupBy, &'a [T], from_raw_parts }
31283047
#[unstable(feature = "slice_group_by", issue = "0")]
31293048
#[derive(Debug)] // FIXME implement Debug to be more user friendly
31303049
pub struct GroupByMut<'a, T: 'a, P> {
3131-
ptr: *mut T,
3132-
end: *mut T,
3050+
slice: &'a mut [T],
31333051
predicate: P,
3134-
_phantom: marker::PhantomData<&'a T>,
31353052
}
31363053

31373054
#[unstable(feature = "slice_group_by", issue = "0")]
3138-
impl<'a, T: 'a, P> GroupByMut<'a, T, P>
3055+
impl<'a, T: 'a, P> GroupByMut<'a, T, P> {
3056+
pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self {
3057+
GroupByMut { slice, predicate }
3058+
}
3059+
}
3060+
3061+
#[unstable(feature = "slice_group_by", issue = "0")]
3062+
impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P>
31393063
where P: FnMut(&T, &T) -> bool,
31403064
{
3141-
/// Returns the remainder of the original slice that is going to be
3142-
/// returned by the iterator.
3143-
pub fn into_remaining(self) -> &'a mut [T] {
3144-
let len = self.remaining_len();
3145-
unsafe { from_raw_parts_mut(self.ptr, len) }
3065+
type Item = &'a mut [T];
3066+
3067+
#[inline]
3068+
fn next(&mut self) -> Option<Self::Item> {
3069+
if self.slice.is_empty() {
3070+
None
3071+
} else {
3072+
let mut len = 1;
3073+
let mut iter = self.slice.windows(2);
3074+
while let Some([l, r]) = iter.next() {
3075+
if (self.predicate)(l, r) { len += 1 } else { break }
3076+
}
3077+
let slice = mem::take(&mut self.slice);
3078+
let (head, tail) = slice.split_at_mut(len);
3079+
self.slice = tail;
3080+
Some(head)
3081+
}
31463082
}
31473083
}
31483084

3149-
group_by!{ struct GroupByMut, &'a mut [T], from_raw_parts_mut }
3085+
#[unstable(feature = "slice_group_by", issue = "0")]
3086+
impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P>
3087+
where P: FnMut(&T, &T) -> bool,
3088+
{
3089+
#[inline]
3090+
fn next_back(&mut self) -> Option<Self::Item> {
3091+
if self.slice.is_empty() {
3092+
None
3093+
} else {
3094+
let mut len = 1;
3095+
let mut iter = self.slice.windows(2);
3096+
while let Some([l, r]) = iter.next_back() {
3097+
if (self.predicate)(l, r) { len += 1 } else { break }
3098+
}
3099+
let slice = mem::take(&mut self.slice);
3100+
let (head, tail) = slice.split_at_mut(slice.len() - len);
3101+
self.slice = head;
3102+
Some(tail)
3103+
}
3104+
}
3105+
}

library/core/src/slice/mod.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,12 +1233,7 @@ impl<T> [T] {
12331233
pub fn group_by<F>(&self, pred: F) -> GroupBy<T, F>
12341234
where F: FnMut(&T, &T) -> bool
12351235
{
1236-
GroupBy {
1237-
ptr: self.as_ptr(),
1238-
end: unsafe { self.as_ptr().add(self.len()) },
1239-
predicate: pred,
1240-
_phantom: marker::PhantomData,
1241-
}
1236+
GroupBy::new(self, pred)
12421237
}
12431238

12441239
/// Returns an iterator over the slice producing non-overlapping mutable
@@ -1267,12 +1262,7 @@ impl<T> [T] {
12671262
pub fn group_by_mut<F>(&mut self, pred: F) -> GroupByMut<T, F>
12681263
where F: FnMut(&T, &T) -> bool
12691264
{
1270-
GroupByMut {
1271-
ptr: self.as_mut_ptr(),
1272-
end: unsafe { self.as_mut_ptr().add(self.len()) },
1273-
predicate: pred,
1274-
_phantom: marker::PhantomData,
1275-
}
1265+
GroupByMut::new(self, pred)
12761266
}
12771267

12781268
/// Divides one slice into two at an index.

0 commit comments

Comments
 (0)