Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add display method to OsStr #120051

Merged
merged 1 commit into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion library/std/src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ pub use core::ffi::FromBytesUntilNulError;
pub use core::ffi::{CStr, FromBytesWithNulError};

#[stable(feature = "rust1", since = "1.0.0")]
#[doc(inline)]
pub use self::os_str::{OsStr, OsString};

#[stable(feature = "core_ffi_c", since = "1.64.0")]
Expand All @@ -181,4 +182,5 @@ pub use core::ffi::c_void;
)]
pub use core::ffi::{VaList, VaListImpl};

mod os_str;
#[unstable(feature = "os_str_display", issue = "120048")]
pub mod os_str;
67 changes: 64 additions & 3 deletions library/std/src/ffi/os_str.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! The [`OsStr`] and [`OsString`] types and associated utilities.

#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -1173,6 +1175,32 @@ impl OsStr {
pub fn eq_ignore_ascii_case<S: AsRef<OsStr>>(&self, other: S) -> bool {
self.inner.eq_ignore_ascii_case(&other.as_ref().inner)
}

/// Returns an object that implements [`Display`] for safely printing an
/// [`OsStr`] that may contain non-Unicode data. This may perform lossy
/// conversion, depending on the platform. If you would like an
/// implementation which escapes the [`OsStr`] please use [`Debug`]
/// instead.
///
/// [`Display`]: fmt::Display
/// [`Debug`]: fmt::Debug
///
/// # Examples
///
/// ```
/// #![feature(os_str_display)]
/// use std::ffi::OsStr;
///
/// let s = OsStr::new("Hello, world!");
/// println!("{}", s.display());
/// ```
#[unstable(feature = "os_str_display", issue = "120048")]
#[must_use = "this does not display the `OsStr`; \
it returns an object that can be displayed"]
#[inline]
pub fn display(&self) -> Display<'_> {
Display { os_str: self }
}
}

#[stable(feature = "box_from_os_str", since = "1.17.0")]
Expand Down Expand Up @@ -1467,9 +1495,42 @@ impl fmt::Debug for OsStr {
}
}

impl OsStr {
pub(crate) fn display(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.inner, formatter)
/// Helper struct for safely printing an [`OsStr`] with [`format!`] and `{}`.
///
/// An [`OsStr`] might contain non-Unicode data. This `struct` implements the
/// [`Display`] trait in a way that mitigates that. It is created by the
/// [`display`](OsStr::display) method on [`OsStr`]. This may perform lossy
/// conversion, depending on the platform. If you would like an implementation
/// which escapes the [`OsStr`] please use [`Debug`] instead.
///
/// # Examples
///
/// ```
/// #![feature(os_str_display)]
/// use std::ffi::OsStr;
///
/// let s = OsStr::new("Hello, world!");
/// println!("{}", s.display());
/// ```
///
/// [`Display`]: fmt::Display
/// [`format!`]: crate::format
#[unstable(feature = "os_str_display", issue = "120048")]
pub struct Display<'a> {
os_str: &'a OsStr,
}

#[unstable(feature = "os_str_display", issue = "120048")]
impl fmt::Debug for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.os_str, f)
}
}

#[unstable(feature = "os_str_display", issue = "120048")]
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.os_str.inner, f)
}
}

Expand Down
10 changes: 5 additions & 5 deletions library/std/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ use crate::rc::Rc;
use crate::str::FromStr;
use crate::sync::Arc;

use crate::ffi::{OsStr, OsString};
use crate::ffi::{os_str, OsStr, OsString};
use crate::sys;
use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR};

Expand Down Expand Up @@ -2725,7 +2725,7 @@ impl Path {
it returns an object that can be displayed"]
#[inline]
pub fn display(&self) -> Display<'_> {
Display { path: self }
Display { inner: self.inner.display() }
}

/// Queries the file system to get information about a file, directory, etc.
Expand Down Expand Up @@ -3032,20 +3032,20 @@ impl fmt::Debug for Path {
/// [`format!`]: crate::format
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Display<'a> {
path: &'a Path,
inner: os_str::Display<'a>,
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.path, f)
fmt::Debug::fmt(&self.inner, f)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.path.inner.display(f)
fmt::Display::fmt(&self.inner, f)
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/rustdoc-js-std/osstring-to-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
const EXPECTED = {
'query': 'OsString -> String',
'others': [
{ 'path': 'std::ffi::OsString', 'name': 'into_string' },
{ 'path': 'std::ffi::os_str::OsString', 'name': 'into_string' },
]
};
Loading