Skip to content

Commit f41ecef

Browse files
committed
std_unicode: impl Clone for .split_whitespace()
Use custom closure structs for the predicates so that the iterator's clone can simply be derived. This should also reduce virtual call overhead by not using function pointers.
1 parent 06fb4d2 commit f41ecef

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

src/libstd_unicode/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@
3636
#![feature(core_char_ext)]
3737
#![feature(decode_utf8)]
3838
#![feature(fused)]
39+
#![feature(fn_traits)]
3940
#![feature(lang_items)]
4041
#![feature(staged_api)]
4142
#![feature(try_from)]
43+
#![feature(unboxed_closures)]
4244

4345
mod tables;
4446
mod u_str;

src/libstd_unicode/u_str.rs

+38-12
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ use core::str::Split;
2626
/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
2727
/// [`str`]: ../../std/primitive.str.html
2828
#[stable(feature = "split_whitespace", since = "1.1.0")]
29+
#[derive(Clone)]
2930
pub struct SplitWhitespace<'a> {
30-
inner: Filter<Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
31+
inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
3132
}
3233

3334
/// Methods for Unicode string slices
@@ -44,17 +45,7 @@ pub trait UnicodeStr {
4445
impl UnicodeStr for str {
4546
#[inline]
4647
fn split_whitespace(&self) -> SplitWhitespace {
47-
fn is_not_empty(s: &&str) -> bool {
48-
!s.is_empty()
49-
}
50-
let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer
51-
52-
fn is_whitespace(c: char) -> bool {
53-
c.is_whitespace()
54-
}
55-
let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer
56-
57-
SplitWhitespace { inner: self.split(is_whitespace).filter(is_not_empty) }
48+
SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
5849
}
5950

6051
#[inline]
@@ -139,6 +130,41 @@ impl<I> Iterator for Utf16Encoder<I>
139130
impl<I> FusedIterator for Utf16Encoder<I>
140131
where I: FusedIterator<Item = char> {}
141132

133+
#[derive(Clone)]
134+
struct IsWhitespace;
135+
136+
impl FnOnce<(char, )> for IsWhitespace {
137+
type Output = bool;
138+
139+
extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
140+
self.call_mut(arg)
141+
}
142+
}
143+
144+
impl FnMut<(char, )> for IsWhitespace {
145+
extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
146+
arg.0.is_whitespace()
147+
}
148+
}
149+
150+
#[derive(Clone)]
151+
struct IsNotEmpty;
152+
153+
impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
154+
type Output = bool;
155+
156+
extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
157+
self.call_mut(arg)
158+
}
159+
}
160+
161+
impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
162+
extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
163+
!arg.0.is_empty()
164+
}
165+
}
166+
167+
142168
#[stable(feature = "split_whitespace", since = "1.1.0")]
143169
impl<'a> Iterator for SplitWhitespace<'a> {
144170
type Item = &'a str;

0 commit comments

Comments
 (0)