Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
1c55a73b
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,发现更多精彩内容 >>
未验证
提交
1c55a73b
编写于
12月 10, 2020
作者:
C
Clément Renault
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement it with only safe code
上级
a891f6ed
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
128 addition
and
163 deletion
+128
-163
library/alloc/tests/slice.rs
library/alloc/tests/slice.rs
+29
-10
library/core/src/slice/iter.rs
library/core/src/slice/iter.rs
+97
-141
library/core/src/slice/mod.rs
library/core/src/slice/mod.rs
+2
-12
未找到文件。
library/alloc/tests/slice.rs
浏览文件 @
1c55a73b
...
...
@@ -1904,24 +1904,43 @@ 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
);
let
mut
iter
=
slice
.group_by
(|
a
,
b
|
a
==
b
);
assert_eq!
(
iter
.next
(),
Some
(
&
[
1
,
1
,
1
][
..
]));
assert_eq!
(
iter
.next_back
(),
Some
(
&
[
2
,
2
,
2
][
..
]));
assert_eq!
(
iter
.next
(),
Some
(
&
[
3
,
3
][
..
]));
assert_eq!
(
iter
.next_back
(),
None
);
}
#[test]
fn
test_group_by_mut
()
{
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
);
let
mut
iter
=
slice
.group_by_mut
(|
a
,
b
|
a
==
b
);
assert_eq!
(
iter
.next_back
(),
Some
(
&
mut
[
2
,
2
,
2
][
..
]));
assert_eq!
(
iter
.next_back
(),
Some
(
&
mut
[
3
,
3
][
..
]));
assert_eq!
(
iter
.next_back
(),
Some
(
&
mut
[
1
,
1
,
1
][
..
]));
assert_eq!
(
iter
.next_back
(),
None
);
let
mut
iter
=
slice
.group_by_mut
(|
a
,
b
|
a
==
b
);
assert_eq!
(
iter
.next
(),
Some
(
&
mut
[
1
,
1
,
1
][
..
]));
assert_eq!
(
iter
.next_back
(),
Some
(
&
mut
[
2
,
2
,
2
][
..
]));
assert_eq!
(
iter
.next
(),
Some
(
&
mut
[
3
,
3
][
..
]));
assert_eq!
(
iter
.next_back
(),
None
);
}
library/core/src/slice/iter.rs
浏览文件 @
1c55a73b
...
...
@@ -2968,127 +2968,6 @@ fn may_have_side_effect() -> bool {
}
}
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].
...
...
@@ -3098,25 +2977,65 @@ impl<'a, T: 'a, P> FusedIterator for $name<'a, T, P>
#[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
,
slice
:
&
'a
[
T
],
predicate
:
P
,
_
phantom
:
marker
::
PhantomData
<&
'a
T
>
,
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
GroupBy
<
'a
,
T
,
P
>
impl
<
'a
,
T
:
'a
,
P
>
GroupBy
<
'a
,
T
,
P
>
{
pub
(
super
)
fn
new
(
slice
:
&
'a
[
T
],
predicate
:
P
)
->
Self
{
GroupBy
{
slice
,
predicate
}
}
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
Iterator
for
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
)
}
type
Item
=
&
'a
[
T
];
#[inline]
fn
next
(
&
mut
self
)
->
Option
<
Self
::
Item
>
{
if
self
.slice
.is_empty
()
{
None
}
else
{
let
mut
len
=
1
;
let
mut
iter
=
self
.slice
.windows
(
2
);
while
let
Some
([
l
,
r
])
=
iter
.next
()
{
if
(
self
.predicate
)(
l
,
r
)
{
len
+=
1
}
else
{
break
}
}
let
(
head
,
tail
)
=
self
.slice
.split_at
(
len
);
self
.slice
=
tail
;
Some
(
head
)
}
}
}
group_by!
{
struct
GroupBy
,
&
'a
[
T
],
from_raw_parts
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
DoubleEndedIterator
for
GroupBy
<
'a
,
T
,
P
>
where
P
:
FnMut
(
&
T
,
&
T
)
->
bool
,
{
#[inline]
fn
next_back
(
&
mut
self
)
->
Option
<
Self
::
Item
>
{
if
self
.slice
.is_empty
()
{
None
}
else
{
let
mut
len
=
1
;
let
mut
iter
=
self
.slice
.windows
(
2
);
while
let
Some
([
l
,
r
])
=
iter
.next_back
()
{
if
(
self
.predicate
)(
l
,
r
)
{
len
+=
1
}
else
{
break
}
}
let
(
head
,
tail
)
=
self
.slice
.split_at
(
self
.slice
.len
()
-
len
);
self
.slice
=
head
;
Some
(
tail
)
}
}
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
FusedIterator
for
GroupBy
<
'a
,
T
,
P
>
where
P
:
FnMut
(
&
T
,
&
T
)
->
bool
,
{
}
/// An iterator over slice in (non-overlapping) mutable chunks separated
/// by a predicate.
...
...
@@ -3128,22 +3047,59 @@ pub fn remaining(&self) -> &[T] {
#[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
,
slice
:
&
'a
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
>
impl
<
'a
,
T
:
'a
,
P
>
GroupByMut
<
'a
,
T
,
P
>
{
pub
(
super
)
fn
new
(
slice
:
&
'a
mut
[
T
],
predicate
:
P
)
->
Self
{
GroupByMut
{
slice
,
predicate
}
}
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
Iterator
for
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
)
}
type
Item
=
&
'a
mut
[
T
];
#[inline]
fn
next
(
&
mut
self
)
->
Option
<
Self
::
Item
>
{
if
self
.slice
.is_empty
()
{
None
}
else
{
let
mut
len
=
1
;
let
mut
iter
=
self
.slice
.windows
(
2
);
while
let
Some
([
l
,
r
])
=
iter
.next
()
{
if
(
self
.predicate
)(
l
,
r
)
{
len
+=
1
}
else
{
break
}
}
let
slice
=
mem
::
take
(
&
mut
self
.slice
);
let
(
head
,
tail
)
=
slice
.split_at_mut
(
len
);
self
.slice
=
tail
;
Some
(
head
)
}
}
}
group_by!
{
struct
GroupByMut
,
&
'a
mut
[
T
],
from_raw_parts_mut
}
#[unstable(feature
=
"slice_group_by"
,
issue
=
"0"
)]
impl
<
'a
,
T
:
'a
,
P
>
DoubleEndedIterator
for
GroupByMut
<
'a
,
T
,
P
>
where
P
:
FnMut
(
&
T
,
&
T
)
->
bool
,
{
#[inline]
fn
next_back
(
&
mut
self
)
->
Option
<
Self
::
Item
>
{
if
self
.slice
.is_empty
()
{
None
}
else
{
let
mut
len
=
1
;
let
mut
iter
=
self
.slice
.windows
(
2
);
while
let
Some
([
l
,
r
])
=
iter
.next_back
()
{
if
(
self
.predicate
)(
l
,
r
)
{
len
+=
1
}
else
{
break
}
}
let
slice
=
mem
::
take
(
&
mut
self
.slice
);
let
(
head
,
tail
)
=
slice
.split_at_mut
(
slice
.len
()
-
len
);
self
.slice
=
head
;
Some
(
tail
)
}
}
}
library/core/src/slice/mod.rs
浏览文件 @
1c55a73b
...
...
@@ -1233,12 +1233,7 @@ pub fn rchunks_exact_mut(&mut self, chunk_size: usize) -> RChunksExactMut<'_, T>
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
,
}
GroupBy
::
new
(
self
,
pred
)
}
/// Returns an iterator over the slice producing non-overlapping mutable
...
...
@@ -1267,12 +1262,7 @@ pub fn group_by<F>(&self, pred: F) -> GroupBy<T, F>
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
,
}
GroupByMut
::
new
(
self
,
pred
)
}
/// Divides one slice into two at an index.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录