Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
a891f6ed
R
Rust
项目概览
int
/
Rust
接近 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
a891f6ed
编写于
12月 10, 2020
作者:
C
Clément Renault
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Introduce the GroupBy and GroupByMut Iterators
上级
e413d89a
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
280 addition
and
0 deletion
+280
-0
library/alloc/src/lib.rs
library/alloc/src/lib.rs
+1
-0
library/alloc/src/slice.rs
library/alloc/src/slice.rs
+2
-0
library/alloc/tests/lib.rs
library/alloc/tests/lib.rs
+1
-0
library/alloc/tests/slice.rs
library/alloc/tests/slice.rs
+27
-0
library/core/src/slice/iter.rs
library/core/src/slice/iter.rs
+180
-0
library/core/src/slice/mod.rs
library/core/src/slice/mod.rs
+68
-0
library/core/tests/lib.rs
library/core/tests/lib.rs
+1
-0
未找到文件。
library/alloc/src/lib.rs
浏览文件 @
a891f6ed
...
...
@@ -140,6 +140,7 @@
#![feature(try_trait)]
#![feature(type_alias_impl_trait)]
#![feature(associated_type_bounds)]
#![feature(slice_group_by)]
// Allow testing this library
#[cfg(test)]
...
...
library/alloc/src/slice.rs
浏览文件 @
a891f6ed
...
...
@@ -118,6 +118,8 @@
pub
use
core
::
slice
::{
RSplit
,
RSplitMut
};
#[stable(feature
=
"rust1"
,
since
=
"1.0.0"
)]
pub
use
core
::
slice
::{
RSplitN
,
RSplitNMut
,
SplitN
,
SplitNMut
};
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
pub
use
core
::
slice
::{
GroupBy
,
GroupByMut
};
////////////////////////////////////////////////////////////////////////////////
// Basic slice extension methods
...
...
library/alloc/tests/lib.rs
浏览文件 @
a891f6ed
...
...
@@ -21,6 +21,7 @@
#![feature(iter_map_while)]
#![feature(int_bits_const)]
#![feature(vecdeque_binary_search)]
#![feature(slice_group_by)]
use
std
::
collections
::
hash_map
::
DefaultHasher
;
use
std
::
hash
::{
Hash
,
Hasher
};
...
...
library/alloc/tests/slice.rs
浏览文件 @
a891f6ed
...
...
@@ -1898,3 +1898,30 @@ fn subslice_patterns() {
m!
(
&
mut
v
,
[
..
]
=>
());
m!
(
&
mut
v
,
[
x
,
..
,
y
]
=>
c!
((
x
,
y
),
(
&
mut
N
,
&
mut
N
),
(
&
mut
N
(
0
),
&
mut
N
(
4
))));
}
#[test]
fn
test_group_by
()
{
let
slice
=
&
[
1
,
1
,
1
,
3
,
3
,
2
,
2
,
2
];
let
mut
iter
=
slice
.group_by
(|
a
,
b
|
a
==
b
);
assert_eq!
(
iter
.next
(),
Some
(
&
[
1
,
1
,
1
][
..
]));
assert_eq!
(
iter
.remaining
(),
&
[
3
,
3
,
2
,
2
,
2
]);
assert_eq!
(
iter
.next
(),
Some
(
&
[
3
,
3
][
..
]));
assert_eq!
(
iter
.next
(),
Some
(
&
[
2
,
2
,
2
][
..
]));
assert_eq!
(
iter
.next
(),
None
);
}
#[test]
fn
test_group_by_rev
()
{
let
slice
=
&
[
1
,
1
,
1
,
3
,
3
,
2
,
2
,
2
];
let
mut
iter
=
slice
.group_by
(|
a
,
b
|
a
==
b
);
assert_eq!
(
iter
.next_back
(),
Some
(
&
[
2
,
2
,
2
][
..
]));
assert_eq!
(
iter
.next_back
(),
Some
(
&
[
3
,
3
][
..
]));
assert_eq!
(
iter
.next_back
(),
Some
(
&
[
1
,
1
,
1
][
..
]));
assert_eq!
(
iter
.next_back
(),
None
);
}
library/core/src/slice/iter.rs
浏览文件 @
a891f6ed
...
...
@@ -2967,3 +2967,183 @@ fn may_have_side_effect() -> bool {
false
}
}
macro_rules!
group_by
{
(
struct
$name:ident
,
$elem:ty
,
$mkslice:ident
)
=>
{
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
$name
<
'a
,
T
,
P
>
{
#[inline]
fn
is_empty
(
&
self
)
->
bool
{
self
.ptr
==
self
.end
}
#[inline]
fn
remaining_len
(
&
self
)
->
usize
{
unsafe
{
self
.end
.offset_from
(
self
.ptr
)
as
usize
}
}
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
Iterator
for
$name
<
'a
,
T
,
P
>
where
P
:
FnMut
(
&
T
,
&
T
)
->
bool
,
{
type
Item
=
$elem
;
fn
next
(
&
mut
self
)
->
Option
<
Self
::
Item
>
{
// we use an unsafe block to avoid bounds checking here.
// this is safe because the only thing we do here is to get
// two elements at `ptr` and `ptr + 1`, bounds checking is done by hand.
unsafe
{
if
self
.is_empty
()
{
return
None
}
let
mut
i
=
0
;
let
mut
ptr
=
self
.ptr
;
// we need to get *two* contiguous elements so we check that:
// - the first element is at the `end - 1` position because
// - the second one will be read from `ptr + 1` that must
// be lower or equal to `end`
while
ptr
!=
self
.end
.sub
(
1
)
{
let
a
=
&*
ptr
;
ptr
=
ptr
.add
(
1
);
let
b
=
&*
ptr
;
i
+=
1
;
if
!
(
self
.predicate
)(
a
,
b
)
{
let
slice
=
$mkslice
(
self
.ptr
,
i
);
self
.ptr
=
ptr
;
return
Some
(
slice
)
}
}
// `i` is either `0` or the slice `length - 1` because either:
// - we have not entered the loop and so `i` is equal to `0`
// the slice length is necessarily `1` because we ensure it is not empty
// - we have entered the loop and we have not early returned
// so `i` is equal to the slice `length - 1`
let
slice
=
$mkslice
(
self
.ptr
,
i
+
1
);
self
.ptr
=
self
.end
;
Some
(
slice
)
}
}
fn
size_hint
(
&
self
)
->
(
usize
,
Option
<
usize
>
)
{
if
self
.is_empty
()
{
return
(
0
,
Some
(
0
))
}
let
len
=
self
.remaining_len
();
(
1
,
Some
(
len
))
}
fn
last
(
mut
self
)
->
Option
<
Self
::
Item
>
{
self
.next_back
()
}
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
DoubleEndedIterator
for
$name
<
'a
,
T
,
P
>
where
P
:
FnMut
(
&
T
,
&
T
)
->
bool
,
{
fn
next_back
(
&
mut
self
)
->
Option
<
Self
::
Item
>
{
// during the loop we retrieve two elements at `ptr` and `ptr - 1`.
unsafe
{
if
self
.is_empty
()
{
return
None
}
let
mut
i
=
0
;
// we ensure that the first element that will be read
// is not under `end` because `end` is out of bound.
let
mut
ptr
=
self
.end
.sub
(
1
);
while
ptr
!=
self
.ptr
{
// we first get `a` that is at the left of `ptr`
// then `b` that is under the `ptr` position.
let
a
=
&*
ptr
.sub
(
1
);
let
b
=
&*
ptr
;
i
+=
1
;
if
!
(
self
.predicate
)(
a
,
b
)
{
// the slice to return starts at the `ptr` position
// and `i` is the length of it.
let
slice
=
$mkslice
(
ptr
,
i
);
// because `end` is always an invalid bound
// we use `ptr` as `end` for the future call to `next`.
self
.end
=
ptr
;
return
Some
(
slice
)
}
ptr
=
ptr
.sub
(
1
);
}
let
slice
=
$mkslice
(
self
.ptr
,
i
+
1
);
self
.ptr
=
self
.end
;
Some
(
slice
)
}
}
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
FusedIterator
for
$name
<
'a
,
T
,
P
>
where
P
:
FnMut
(
&
T
,
&
T
)
->
bool
,
{
}
}
}
/// An iterator over slice in (non-overlapping) chunks separated by a predicate.
///
/// This struct is created by the [`group_by`] method on [slices].
///
/// [`group_by`]: ../../std/primitive.slice.html#method.group_by
/// [slices]: ../../std/primitive.slice.html
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
#[derive(Debug)]
// FIXME implement Debug to be more user friendly
pub
struct
GroupBy
<
'a
,
T
:
'a
,
P
>
{
ptr
:
*
const
T
,
end
:
*
const
T
,
predicate
:
P
,
_
phantom
:
marker
::
PhantomData
<&
'a
T
>
,
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
GroupBy
<
'a
,
T
,
P
>
where
P
:
FnMut
(
&
T
,
&
T
)
->
bool
,
{
/// Returns the remainder of the original slice that is going to be
/// returned by the iterator.
pub
fn
remaining
(
&
self
)
->
&
[
T
]
{
let
len
=
self
.remaining_len
();
unsafe
{
from_raw_parts
(
self
.ptr
,
len
)
}
}
}
group_by!
{
struct
GroupBy
,
&
'a
[
T
],
from_raw_parts
}
/// An iterator over slice in (non-overlapping) mutable chunks separated
/// by a predicate.
///
/// This struct is created by the [`group_by_mut`] method on [slices].
///
/// [`group_by_mut`]: ../../std/primitive.slice.html#method.group_by_mut
/// [slices]: ../../std/primitive.slice.html
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
#[derive(Debug)]
// FIXME implement Debug to be more user friendly
pub
struct
GroupByMut
<
'a
,
T
:
'a
,
P
>
{
ptr
:
*
mut
T
,
end
:
*
mut
T
,
predicate
:
P
,
_
phantom
:
marker
::
PhantomData
<&
'a
T
>
,
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
GroupByMut
<
'a
,
T
,
P
>
where
P
:
FnMut
(
&
T
,
&
T
)
->
bool
,
{
/// Returns the remainder of the original slice that is going to be
/// returned by the iterator.
pub
fn
into_remaining
(
self
)
->
&
'a
mut
[
T
]
{
let
len
=
self
.remaining_len
();
unsafe
{
from_raw_parts_mut
(
self
.ptr
,
len
)
}
}
}
group_by!
{
struct
GroupByMut
,
&
'a
mut
[
T
],
from_raw_parts_mut
}
library/core/src/slice/mod.rs
浏览文件 @
a891f6ed
...
...
@@ -1207,6 +1207,74 @@ pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T>
RChunksExactMut
::
new
(
self
,
chunk_size
)
}
/// Returns an iterator over the slice producing non-overlapping runs
/// of elements using the predicate to separate them.
///
/// The predicate is called on two elements following themselves,
/// it means the predicate is called on `slice[0]` and `slice[1]`
/// then on `slice[1]` and `slice[2]` and so on.
///
/// # Examples
///
/// ```
/// #![feature(slice_group_by)]
///
/// let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
///
/// let mut iter = slice.group_by(|a, b| a == b);
///
/// assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
/// assert_eq!(iter.next(), Some(&[3, 3][..]));
/// assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
/// assert_eq!(iter.next(), None);
/// ```
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
#[inline]
pub
fn
group_by
<
F
>
(
&
self
,
pred
:
F
)
->
GroupBy
<
T
,
F
>
where
F
:
FnMut
(
&
T
,
&
T
)
->
bool
{
GroupBy
{
ptr
:
self
.as_ptr
(),
end
:
unsafe
{
self
.as_ptr
()
.add
(
self
.len
())
},
predicate
:
pred
,
_
phantom
:
marker
::
PhantomData
,
}
}
/// Returns an iterator over the slice producing non-overlapping mutable
/// runs of elements using the predicate to separate them.
///
/// The predicate is called on two elements following themselves,
/// it means the predicate is called on `slice[0]` and `slice[1]`
/// then on `slice[1]` and `slice[2]` and so on.
///
/// # Examples
///
/// ```
/// #![feature(slice_group_by)]
///
/// let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2];
///
/// let mut iter = slice.group_by_mut(|a, b| a == b);
///
/// assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
/// assert_eq!(iter.next(), Some(&mut [3, 3][..]));
/// assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
/// assert_eq!(iter.next(), None);
/// ```
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
#[inline]
pub
fn
group_by_mut
<
F
>
(
&
mut
self
,
pred
:
F
)
->
GroupByMut
<
T
,
F
>
where
F
:
FnMut
(
&
T
,
&
T
)
->
bool
{
GroupByMut
{
ptr
:
self
.as_mut_ptr
(),
end
:
unsafe
{
self
.as_mut_ptr
()
.add
(
self
.len
())
},
predicate
:
pred
,
_
phantom
:
marker
::
PhantomData
,
}
}
/// Divides one slice into two at an index.
///
/// The first will contain all indices from `[0, mid)` (excluding
...
...
library/core/tests/lib.rs
浏览文件 @
a891f6ed
...
...
@@ -65,6 +65,7 @@
#![feature(nonzero_leading_trailing_zeros)]
#![feature(const_option)]
#![feature(integer_atomics)]
#![feature(slice_group_by)]
#![deny(unsafe_op_in_unsafe_fn)]
extern
crate
test
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录