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.
This commit is contained in:
Ulrik Sverdrup 2017-04-30 21:07:39 +02:00
parent 06fb4d2564
commit f41ecef6d5
2 changed files with 40 additions and 12 deletions
src/libstd_unicode

View File

@ -36,9 +36,11 @@
#![feature(core_char_ext)]
#![feature(decode_utf8)]
#![feature(fused)]
#![feature(fn_traits)]
#![feature(lang_items)]
#![feature(staged_api)]
#![feature(try_from)]
#![feature(unboxed_closures)]
mod tables;
mod u_str;

View File

@ -26,8 +26,9 @@ use core::str::Split;
/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
/// [`str`]: ../../std/primitive.str.html
#[stable(feature = "split_whitespace", since = "1.1.0")]
#[derive(Clone)]
pub struct SplitWhitespace<'a> {
inner: Filter<Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
}
/// Methods for Unicode string slices
@ -44,17 +45,7 @@ pub trait UnicodeStr {
impl UnicodeStr for str {
#[inline]
fn split_whitespace(&self) -> SplitWhitespace {
fn is_not_empty(s: &&str) -> bool {
!s.is_empty()
}
let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer
fn is_whitespace(c: char) -> bool {
c.is_whitespace()
}
let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer
SplitWhitespace { inner: self.split(is_whitespace).filter(is_not_empty) }
SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
}
#[inline]
@ -139,6 +130,41 @@ impl<I> Iterator for Utf16Encoder<I>
impl<I> FusedIterator for Utf16Encoder<I>
where I: FusedIterator<Item = char> {}
#[derive(Clone)]
struct IsWhitespace;
impl FnOnce<(char, )> for IsWhitespace {
type Output = bool;
extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
self.call_mut(arg)
}
}
impl FnMut<(char, )> for IsWhitespace {
extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
arg.0.is_whitespace()
}
}
#[derive(Clone)]
struct IsNotEmpty;
impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
type Output = bool;
extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
self.call_mut(arg)
}
}
impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
!arg.0.is_empty()
}
}
#[stable(feature = "split_whitespace", since = "1.1.0")]
impl<'a> Iterator for SplitWhitespace<'a> {
type Item = &'a str;