diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index bb577acf769d..fbdf7f5ecacc 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -745,7 +745,7 @@ impl OsStr {
without modifying the original"]
#[inline]
pub fn to_str(&self) -> Option<&str> {
- self.inner.to_str()
+ self.inner.to_str().ok()
}
/// Converts an `OsStr` to a [Cow]<[str]>.
@@ -1165,6 +1165,24 @@ impl<'a> From> for OsString {
}
}
+#[stable(feature = "str_tryfrom_osstr_impl", since = "CURRENT_RUSTC_VERSION")]
+impl<'a> TryFrom<&'a OsStr> for &'a str {
+ type Error = crate::str::Utf8Error;
+
+ /// Tries to convert an `&OsStr` to a `&str`.
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// let as_str = <&str>::try_from(os_str).unwrap();
+ /// assert_eq!(as_str, "foo");
+ /// ```
+ fn try_from(value: &'a OsStr) -> Result {
+ value.inner.to_str()
+ }
+}
+
#[stable(feature = "box_default_extra", since = "1.17.0")]
impl Default for Box {
#[inline]
diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs
index 142fcb9ed0b7..f7333fd5a1fe 100644
--- a/library/std/src/sys/unix/os_str.rs
+++ b/library/std/src/sys/unix/os_str.rs
@@ -207,8 +207,8 @@ impl Slice {
unsafe { Slice::from_os_str_bytes_unchecked(s.as_bytes()) }
}
- pub fn to_str(&self) -> Option<&str> {
- str::from_utf8(&self.inner).ok()
+ pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
+ str::from_utf8(&self.inner)
}
pub fn to_string_lossy(&self) -> Cow<'_, str> {
diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs
index 611f0d040f0e..16c4f55c6879 100644
--- a/library/std/src/sys/windows/os_str.rs
+++ b/library/std/src/sys/windows/os_str.rs
@@ -166,7 +166,7 @@ impl Slice {
unsafe { mem::transmute(Wtf8::from_str(s)) }
}
- pub fn to_str(&self) -> Option<&str> {
+ pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
self.inner.as_str()
}
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 31bb0ad25a65..c9d3e13cf0c5 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -626,13 +626,8 @@ impl Wtf8 {
///
/// This does not copy the data.
#[inline]
- pub fn as_str(&self) -> Option<&str> {
- // Well-formed WTF-8 is also well-formed UTF-8
- // if and only if it contains no surrogate.
- match self.next_surrogate(0) {
- None => Some(unsafe { str::from_utf8_unchecked(&self.bytes) }),
- Some(_) => None,
- }
+ pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
+ str::from_utf8(&self.bytes)
}
/// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`.
diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/std/src/sys_common/wtf8/tests.rs
index 1a302d646941..a07bbe6d7e42 100644
--- a/library/std/src/sys_common/wtf8/tests.rs
+++ b/library/std/src/sys_common/wtf8/tests.rs
@@ -521,11 +521,11 @@ fn wtf8_code_points() {
#[test]
fn wtf8_as_str() {
- assert_eq!(Wtf8::from_str("").as_str(), Some(""));
- assert_eq!(Wtf8::from_str("aé 💩").as_str(), Some("aé 💩"));
+ assert_eq!(Wtf8::from_str("").as_str(), Ok(""));
+ assert_eq!(Wtf8::from_str("aé 💩").as_str(), Ok("aé 💩"));
let mut string = Wtf8Buf::new();
string.push(CodePoint::from_u32(0xD800).unwrap());
- assert_eq!(string.as_str(), None);
+ assert!(string.as_str().is_err());
}
#[test]