From 6741241f4046aea4014b1a23618593fb481c8606 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Tue, 1 Oct 2013 14:03:41 -0700 Subject: [PATCH] path2: Add format helpers .display() and .filename_display() These methods return an object that can be formatted using {} to print display strings. Path itself does not implement fmt::Default to avoid accidental usage of display strings in incorrect places (e.g. process arguments). --- src/libstd/path2/mod.rs | 41 +++++++++++++++++++++++++++++++++++++ src/libstd/path2/posix.rs | 23 +++++++++++++++++++++ src/libstd/path2/windows.rs | 19 +++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/src/libstd/path2/mod.rs b/src/libstd/path2/mod.rs index e385cea51f9d..38a48866e224 100644 --- a/src/libstd/path2/mod.rs +++ b/src/libstd/path2/mod.rs @@ -13,6 +13,7 @@ use container::Container; use c_str::CString; use clone::Clone; +use fmt; use iter::Iterator; use option::{Option, None, Some}; use str; @@ -185,6 +186,21 @@ pub trait GenericPath: Clone + GenericPathUnsafe { s } + /// Returns an object that implements `fmt::Default` for printing paths + /// + /// This will print the equivalent of `to_display_str()` when used with a {} format parameter. + fn display<'a>(&'a self) -> Display<'a, Self> { + Display{ path: self } + } + + /// Returns an object that implements `fmt::Default` for printing filenames + /// + /// This will print the equivalent of `to_filename_display_str()` when used with a {} + /// format parameter. If there is no filename, nothing will be printed. + fn filename_display<'a>(&'a self) -> FilenameDisplay<'a, Self> { + FilenameDisplay{ path: self } + } + /// Returns the directory component of `self`, as a byte vector (with no trailing separator). /// If `self` has no directory component, returns ['.']. fn dirname<'a>(&'a self) -> &'a [u8]; @@ -661,6 +677,31 @@ pub trait GenericPathUnsafe { } } +/// Helper struct for printing paths with format!() +pub struct Display<'self, P> { + priv path: &'self P +} +/// Helper struct for printing filenames with format!() +pub struct FilenameDisplay<'self, P> { + priv path: &'self P +} + +impl<'self, P: GenericPath> fmt::Default for Display<'self, P> { + fn fmt(d: &Display

, f: &mut fmt::Formatter) { + do d.path.with_display_str |s| { + f.pad(s) + } + } +} + +impl<'self, P: GenericPath> fmt::Default for FilenameDisplay<'self, P> { + fn fmt(d: &FilenameDisplay

, f: &mut fmt::Formatter) { + do d.path.with_filename_display_str |s| { + f.pad(s.unwrap_or("")) + } + } +} + #[inline(always)] fn contains_nul(v: &[u8]) -> bool { v.iter().any(|&x| x == 0) diff --git a/src/libstd/path2/posix.rs b/src/libstd/path2/posix.rs index 233458dfc9b1..4aa2eb531e5c 100644 --- a/src/libstd/path2/posix.rs +++ b/src/libstd/path2/posix.rs @@ -730,6 +730,29 @@ mod tests { assert!(called); } + #[test] + fn test_display() { + macro_rules! t( + ($path:expr, $exp:expr, $expf:expr) => ( + { + let path = Path::from_vec($path); + let f = format!("{}", path.display()); + assert_eq!(f.as_slice(), $exp); + let f = format!("{}", path.filename_display()); + assert_eq!(f.as_slice(), $expf); + } + ) + ) + + t!(b!("foo"), "foo", "foo"); + t!(b!("foo/bar"), "foo/bar", "bar"); + t!(b!("/"), "/", ""); + t!(b!("foo", 0xff), "foo\uFFFD", "foo\uFFFD"); + t!(b!("foo", 0xff, "/bar"), "foo\uFFFD/bar", "bar"); + t!(b!("foo/", 0xff, "bar"), "foo/\uFFFDbar", "\uFFFDbar"); + t!(b!(0xff, "foo/bar", 0xff), "\uFFFDfoo/bar\uFFFD", "bar\uFFFD"); + } + #[test] fn test_components() { macro_rules! t( diff --git a/src/libstd/path2/windows.rs b/src/libstd/path2/windows.rs index c23dc86d7dfb..7cc7a5610bde 100644 --- a/src/libstd/path2/windows.rs +++ b/src/libstd/path2/windows.rs @@ -1457,6 +1457,25 @@ mod tests { assert!(called); } + #[test] + fn test_display() { + macro_rules! t( + ($path:expr, $exp:expr, $expf:expr) => ( + { + let path = Path::from_str($path); + let f = format!("{}", path.display()); + assert_eq!(f.as_slice(), $exp); + let f = format!("{}", path.filename_display()); + assert_eq!(f.as_slice(), $expf); + } + ) + ) + + t!("foo", "foo", "foo"); + t!("foo\\bar", "foo\\bar", "bar"); + t!("\\", "\\", ""); + } + #[test] fn test_components() { macro_rules! t(