about summary refs log tree commit diff
path: root/src/libstd_unicode
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2017-04-30 21:07:39 +0200
committerUlrik Sverdrup <bluss@users.noreply.github.com>2017-04-30 21:20:20 +0200
commitf41ecef6d52200743b3672346a59fc1e2068e9e8 (patch)
tree855808fb4a32b43b4d207f3112c7c91af4cf6aa2 /src/libstd_unicode
parent06fb4d25642a3f223db1441972dd5962085cfba1 (diff)
downloadrust-f41ecef6d52200743b3672346a59fc1e2068e9e8.tar.gz
rust-f41ecef6d52200743b3672346a59fc1e2068e9e8.zip
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.
Diffstat (limited to 'src/libstd_unicode')
-rw-r--r--src/libstd_unicode/lib.rs2
-rw-r--r--src/libstd_unicode/u_str.rs50
2 files changed, 40 insertions, 12 deletions
diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs
index 7e5ab1a54ab..d63878a7a7c 100644
--- a/src/libstd_unicode/lib.rs
+++ b/src/libstd_unicode/lib.rs
@@ -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;
diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs
index 770b67acd49..e138e71c9c1 100644
--- a/src/libstd_unicode/u_str.rs
+++ b/src/libstd_unicode/u_str.rs
@@ -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;