Skip to content

Commit

Permalink
Auto merge of rust-lang#41659 - bluss:clone-split-whitespace, r=aturon
Browse files Browse the repository at this point in the history
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 rust-lang#41655
  • Loading branch information
bors committed May 10, 2017
2 parents db1c9eb + 41aeb9d commit 58b33ad
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/libstd_unicode/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
54 changes: 42 additions & 12 deletions src/libstd_unicode/u_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 58b33ad

Please sign in to comment.