Auto merge of #41659 - bluss:clone-split-whitespace, r=aturon

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.

Fixes #41655
This commit is contained in:
bors 2017-05-10 03:27:36 +00:00
commit 58b33ad70c
2 changed files with 44 additions and 12 deletions

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,45 @@ 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;
#[inline]
extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
self.call_mut(arg)
}
}
impl FnMut<(char, )> for IsWhitespace {
#[inline]
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;
#[inline]
extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
self.call_mut(arg)
}
}
impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
#[inline]
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;