Skip to content

Commit 6741241

Browse files
committed
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).
1 parent 3a2735c commit 6741241

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

src/libstd/path2/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use container::Container;
1414
use c_str::CString;
1515
use clone::Clone;
16+
use fmt;
1617
use iter::Iterator;
1718
use option::{Option, None, Some};
1819
use str;
@@ -185,6 +186,21 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
185186
s
186187
}
187188

189+
/// Returns an object that implements `fmt::Default` for printing paths
190+
///
191+
/// This will print the equivalent of `to_display_str()` when used with a {} format parameter.
192+
fn display<'a>(&'a self) -> Display<'a, Self> {
193+
Display{ path: self }
194+
}
195+
196+
/// Returns an object that implements `fmt::Default` for printing filenames
197+
///
198+
/// This will print the equivalent of `to_filename_display_str()` when used with a {}
199+
/// format parameter. If there is no filename, nothing will be printed.
200+
fn filename_display<'a>(&'a self) -> FilenameDisplay<'a, Self> {
201+
FilenameDisplay{ path: self }
202+
}
203+
188204
/// Returns the directory component of `self`, as a byte vector (with no trailing separator).
189205
/// If `self` has no directory component, returns ['.'].
190206
fn dirname<'a>(&'a self) -> &'a [u8];
@@ -661,6 +677,31 @@ pub trait GenericPathUnsafe {
661677
}
662678
}
663679

680+
/// Helper struct for printing paths with format!()
681+
pub struct Display<'self, P> {
682+
priv path: &'self P
683+
}
684+
/// Helper struct for printing filenames with format!()
685+
pub struct FilenameDisplay<'self, P> {
686+
priv path: &'self P
687+
}
688+
689+
impl<'self, P: GenericPath> fmt::Default for Display<'self, P> {
690+
fn fmt(d: &Display<P>, f: &mut fmt::Formatter) {
691+
do d.path.with_display_str |s| {
692+
f.pad(s)
693+
}
694+
}
695+
}
696+
697+
impl<'self, P: GenericPath> fmt::Default for FilenameDisplay<'self, P> {
698+
fn fmt(d: &FilenameDisplay<P>, f: &mut fmt::Formatter) {
699+
do d.path.with_filename_display_str |s| {
700+
f.pad(s.unwrap_or(""))
701+
}
702+
}
703+
}
704+
664705
#[inline(always)]
665706
fn contains_nul(v: &[u8]) -> bool {
666707
v.iter().any(|&x| x == 0)

src/libstd/path2/posix.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,29 @@ mod tests {
730730
assert!(called);
731731
}
732732

733+
#[test]
734+
fn test_display() {
735+
macro_rules! t(
736+
($path:expr, $exp:expr, $expf:expr) => (
737+
{
738+
let path = Path::from_vec($path);
739+
let f = format!("{}", path.display());
740+
assert_eq!(f.as_slice(), $exp);
741+
let f = format!("{}", path.filename_display());
742+
assert_eq!(f.as_slice(), $expf);
743+
}
744+
)
745+
)
746+
747+
t!(b!("foo"), "foo", "foo");
748+
t!(b!("foo/bar"), "foo/bar", "bar");
749+
t!(b!("/"), "/", "");
750+
t!(b!("foo", 0xff), "foo\uFFFD", "foo\uFFFD");
751+
t!(b!("foo", 0xff, "/bar"), "foo\uFFFD/bar", "bar");
752+
t!(b!("foo/", 0xff, "bar"), "foo/\uFFFDbar", "\uFFFDbar");
753+
t!(b!(0xff, "foo/bar", 0xff), "\uFFFDfoo/bar\uFFFD", "bar\uFFFD");
754+
}
755+
733756
#[test]
734757
fn test_components() {
735758
macro_rules! t(

src/libstd/path2/windows.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,25 @@ mod tests {
14571457
assert!(called);
14581458
}
14591459
1460+
#[test]
1461+
fn test_display() {
1462+
macro_rules! t(
1463+
($path:expr, $exp:expr, $expf:expr) => (
1464+
{
1465+
let path = Path::from_str($path);
1466+
let f = format!("{}", path.display());
1467+
assert_eq!(f.as_slice(), $exp);
1468+
let f = format!("{}", path.filename_display());
1469+
assert_eq!(f.as_slice(), $expf);
1470+
}
1471+
)
1472+
)
1473+
1474+
t!("foo", "foo", "foo");
1475+
t!("foo\\bar", "foo\\bar", "bar");
1476+
t!("\\", "\\", "");
1477+
}
1478+
14601479
#[test]
14611480
fn test_components() {
14621481
macro_rules! t(

0 commit comments

Comments
 (0)