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).
This commit is contained in:
Kevin Ballard 2013-10-01 14:03:41 -07:00
parent 3a2735cb11
commit 6741241f40
3 changed files with 83 additions and 0 deletions

View file

@ -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<P>, 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<P>, 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)

View file

@ -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(

View file

@ -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(