about summary refs log tree commit diff
path: root/src/libstd/path
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-02-08 05:01:30 -0800
committerbors <bors@rust-lang.org>2014-02-08 05:01:30 -0800
commit5acc998ed9b76d9c00849e007101f9c33b17c6c4 (patch)
tree1f1a5ad2080acda5446285f9da7077938cddd9df /src/libstd/path
parent548b8cec199c28c102fd98d6dd2833d3a171e7d0 (diff)
parent1d17c2129ec696d81e6c6caee8b1740dd9509090 (diff)
downloadrust-5acc998ed9b76d9c00849e007101f9c33b17c6c4.tar.gz
rust-5acc998ed9b76d9c00849e007101f9c33b17c6c4.zip
auto merge of #12098 : kballard/rust/from_utf8_lossy_tweak, r=huonw
MaybeOwned allows from_utf8_lossy to avoid allocation if there are no
invalid bytes in the input.

Before:
```
test str::bench::from_utf8_lossy_100_ascii                      ... bench:       183 ns/iter (+/- 5)
test str::bench::from_utf8_lossy_100_invalid                    ... bench:       341 ns/iter (+/- 15)
test str::bench::from_utf8_lossy_100_multibyte                  ... bench:       227 ns/iter (+/- 13)
test str::bench::from_utf8_lossy_invalid                        ... bench:       102 ns/iter (+/- 4)
test str::bench::is_utf8_100_ascii                              ... bench:         2 ns/iter (+/- 0)
test str::bench::is_utf8_100_multibyte                          ... bench:         2 ns/iter (+/- 0)
```

Now:
```
test str::bench::from_utf8_lossy_100_ascii                      ... bench:        96 ns/iter (+/- 4)
test str::bench::from_utf8_lossy_100_invalid                    ... bench:       318 ns/iter (+/- 10)
test str::bench::from_utf8_lossy_100_multibyte                  ... bench:       105 ns/iter (+/- 2)
test str::bench::from_utf8_lossy_invalid                        ... bench:       105 ns/iter (+/- 2)
test str::bench::is_utf8_100_ascii                              ... bench:         2 ns/iter (+/- 0)
test str::bench::is_utf8_100_multibyte                          ... bench:         2 ns/iter (+/- 0)
```
Diffstat (limited to 'src/libstd/path')
-rw-r--r--src/libstd/path/mod.rs49
-rw-r--r--src/libstd/path/posix.rs16
-rw-r--r--src/libstd/path/windows.rs16
3 files changed, 37 insertions, 44 deletions
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
index 18f28994cba..ed0ce201750 100644
--- a/src/libstd/path/mod.rs
+++ b/src/libstd/path/mod.rs
@@ -70,7 +70,7 @@ use fmt;
 use iter::Iterator;
 use option::{Option, None, Some};
 use str;
-use str::{OwnedStr, Str, StrSlice};
+use str::{MaybeOwned, OwnedStr, Str, StrSlice, from_utf8_lossy};
 use to_str::ToStr;
 use vec;
 use vec::{CloneableVector, OwnedCloneableVector, OwnedVector, Vector};
@@ -495,7 +495,7 @@ pub struct Display<'a, P> {
 
 impl<'a, P: GenericPath> fmt::Show for Display<'a, P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.with_str(|s| f.pad(s))
+        self.as_maybe_owned().as_slice().fmt(f)
     }
 }
 
@@ -505,33 +505,25 @@ impl<'a, P: GenericPath> ToStr for Display<'a, P> {
     /// If the path is not UTF-8, invalid sequences with be replaced with the
     /// unicode replacement char. This involves allocation.
     fn to_str(&self) -> ~str {
-        if self.filename {
-            match self.path.filename() {
-                None => ~"",
-                Some(v) => str::from_utf8_lossy(v)
-            }
-        } else {
-            str::from_utf8_lossy(self.path.as_vec())
-        }
+        self.as_maybe_owned().into_owned()
     }
 }
 
 impl<'a, P: GenericPath> Display<'a, P> {
-    /// Provides the path as a string to a closure
+    /// Returns the path as a possibly-owned string.
     ///
     /// If the path is not UTF-8, invalid sequences will be replaced with the
     /// unicode replacement char. This involves allocation.
     #[inline]
-    pub fn with_str<T>(&self, f: |&str| -> T) -> T {
-        let opt = if self.filename { self.path.filename_str() }
-                  else { self.path.as_str() };
-        match opt {
-            Some(s) => f(s),
-            None => {
-                let s = self.to_str();
-                f(s.as_slice())
+    pub fn as_maybe_owned(&self) -> MaybeOwned<'a> {
+        from_utf8_lossy(if self.filename {
+            match self.path.filename() {
+                None => &[],
+                Some(v) => v
             }
-        }
+        } else {
+            self.path.as_vec()
+        })
     }
 }
 
@@ -591,6 +583,23 @@ impl BytesContainer for CString {
     }
 }
 
+impl<'a> BytesContainer for str::MaybeOwned<'a> {
+    #[inline]
+    fn container_as_bytes<'b>(&'b self) -> &'b [u8] {
+        self.as_slice().as_bytes()
+    }
+    #[inline]
+    fn container_into_owned_bytes(self) -> ~[u8] {
+        self.into_owned().into_bytes()
+    }
+    #[inline]
+    fn container_as_str<'b>(&'b self) -> Option<&'b str> {
+        Some(self.as_slice())
+    }
+    #[inline]
+    fn is_str(_: Option<str::MaybeOwned>) -> bool { true }
+}
+
 #[inline(always)]
 fn contains_nul(v: &[u8]) -> bool {
     v.iter().any(|&x| x == 0)
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 6970ebfb15d..f8e9d0ae344 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -564,24 +564,16 @@ mod tests {
         macro_rules! t(
             ($path:expr, $exp:expr) => (
                 {
-                    let mut called = false;
                     let path = Path::new($path);
-                    path.display().with_str(|s| {
-                        assert_eq!(s, $exp);
-                        called = true;
-                    });
-                    assert!(called);
+                    let mo = path.display().as_maybe_owned();
+                    assert_eq!(mo.as_slice(), $exp);
                 }
             );
             ($path:expr, $exp:expr, filename) => (
                 {
-                    let mut called = false;
                     let path = Path::new($path);
-                    path.filename_display().with_str(|s| {
-                        assert_eq!(s, $exp);
-                        called = true;
-                    });
-                    assert!(called);
+                    let mo = path.filename_display().as_maybe_owned();
+                    assert_eq!(mo.as_slice(), $exp);
                 }
             )
         )
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 90154adb7fe..972b7d178a1 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -1278,20 +1278,12 @@ mod tests {
         let path = Path::new(b!("\\"));
         assert_eq!(path.filename_display().to_str(), ~"");
 
-        let mut called = false;
         let path = Path::new("foo");
-        path.display().with_str(|s| {
-            assert_eq!(s, "foo");
-            called = true;
-        });
-        assert!(called);
-        called = false;
+        let mo = path.display().as_maybe_owned();
+        assert_eq!(mo.as_slice(), "foo");
         let path = Path::new(b!("\\"));
-        path.filename_display().with_str(|s| {
-            assert_eq!(s, "");
-            called = true;
-        });
-        assert!(called);
+        let mo = path.filename_display().as_maybe_owned();
+        assert_eq!(mo.as_slice(), "");
     }
 
     #[test]