Skip to content

Commit 4efdb5c

Browse files
authored
Rollup merge of #98202 - aticu:impl_tryfrom_osstr_for_str, r=Amanieu
Implement `TryFrom<&OsStr>` for `&str` Recently when trying to work with `&OsStr` I was surprised to find this `impl` missing. Since the `to_str` method already existed the actual implementation is fairly non-controversial, except for maybe the choice of the error type. I chose an opaque error here instead of something like `std::str::Utf8Error`, since that would already make a number of assumption about the underlying implementation of `OsStr`. As this is a trait implementation, it is insta-stable, if I'm not mistaken? Either way this will need an FCP. I chose "1.64.0" as the version, since this is unlikely to land before the beta cut-off. `@rustbot` modify labels: +T-libs-api API Change Proposal: #99031 (accepted)
2 parents 7b0eac4 + e3a1a11 commit 4efdb5c

File tree

5 files changed

+27
-14
lines changed

5 files changed

+27
-14
lines changed

library/std/src/ffi/os_str.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ impl OsStr {
745745
without modifying the original"]
746746
#[inline]
747747
pub fn to_str(&self) -> Option<&str> {
748-
self.inner.to_str()
748+
self.inner.to_str().ok()
749749
}
750750

751751
/// Converts an `OsStr` to a <code>[Cow]<[str]></code>.
@@ -1165,6 +1165,24 @@ impl<'a> From<Cow<'a, OsStr>> for OsString {
11651165
}
11661166
}
11671167

1168+
#[stable(feature = "str_tryfrom_osstr_impl", since = "CURRENT_RUSTC_VERSION")]
1169+
impl<'a> TryFrom<&'a OsStr> for &'a str {
1170+
type Error = crate::str::Utf8Error;
1171+
1172+
/// Tries to convert an `&OsStr` to a `&str`.
1173+
///
1174+
/// ```
1175+
/// use std::ffi::OsStr;
1176+
///
1177+
/// let os_str = OsStr::new("foo");
1178+
/// let as_str = <&str>::try_from(os_str).unwrap();
1179+
/// assert_eq!(as_str, "foo");
1180+
/// ```
1181+
fn try_from(value: &'a OsStr) -> Result<Self, Self::Error> {
1182+
value.inner.to_str()
1183+
}
1184+
}
1185+
11681186
#[stable(feature = "box_default_extra", since = "1.17.0")]
11691187
impl Default for Box<OsStr> {
11701188
#[inline]

library/std/src/sys/unix/os_str.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ impl Slice {
207207
unsafe { Slice::from_os_str_bytes_unchecked(s.as_bytes()) }
208208
}
209209

210-
pub fn to_str(&self) -> Option<&str> {
211-
str::from_utf8(&self.inner).ok()
210+
pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
211+
str::from_utf8(&self.inner)
212212
}
213213

214214
pub fn to_string_lossy(&self) -> Cow<'_, str> {

library/std/src/sys/windows/os_str.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ impl Slice {
166166
unsafe { mem::transmute(Wtf8::from_str(s)) }
167167
}
168168

169-
pub fn to_str(&self) -> Option<&str> {
169+
pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
170170
self.inner.as_str()
171171
}
172172

library/std/src/sys_common/wtf8.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -626,13 +626,8 @@ impl Wtf8 {
626626
///
627627
/// This does not copy the data.
628628
#[inline]
629-
pub fn as_str(&self) -> Option<&str> {
630-
// Well-formed WTF-8 is also well-formed UTF-8
631-
// if and only if it contains no surrogate.
632-
match self.next_surrogate(0) {
633-
None => Some(unsafe { str::from_utf8_unchecked(&self.bytes) }),
634-
Some(_) => None,
635-
}
629+
pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
630+
str::from_utf8(&self.bytes)
636631
}
637632

638633
/// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`.

library/std/src/sys_common/wtf8/tests.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -521,11 +521,11 @@ fn wtf8_code_points() {
521521

522522
#[test]
523523
fn wtf8_as_str() {
524-
assert_eq!(Wtf8::from_str("").as_str(), Some(""));
525-
assert_eq!(Wtf8::from_str("aé 💩").as_str(), Some("aé 💩"));
524+
assert_eq!(Wtf8::from_str("").as_str(), Ok(""));
525+
assert_eq!(Wtf8::from_str("aé 💩").as_str(), Ok("aé 💩"));
526526
let mut string = Wtf8Buf::new();
527527
string.push(CodePoint::from_u32(0xD800).unwrap());
528-
assert_eq!(string.as_str(), None);
528+
assert!(string.as_str().is_err());
529529
}
530530

531531
#[test]

0 commit comments

Comments
 (0)