diff --git a/crates/std/src/ffi/c_str.rs b/crates/std/src/ffi/c_str.rs
index a7d1de4..cb0ca5d 100644
--- a/crates/std/src/ffi/c_str.rs
+++ b/crates/std/src/ffi/c_str.rs
@@ -1,7 +1,14 @@
//! [`CStr`], [`CString`], and related types.
+
+#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
pub use alloc::ffi::c_str::FromVecWithNulError;
+#[stable(feature = "cstring_into", since = "1.7.0")]
pub use alloc::ffi::c_str::IntoStringError;
+#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc::ffi::c_str::{CString, NulError};
+#[stable(feature = "rust1", since = "1.0.0")]
pub use core::ffi::c_str::CStr;
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
pub use core::ffi::c_str::FromBytesUntilNulError;
+#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use core::ffi::c_str::FromBytesWithNulError;
diff --git a/crates/std/src/ffi/mod.rs b/crates/std/src/ffi/mod.rs
index 7f24b7b..999bd5e 100644
--- a/crates/std/src/ffi/mod.rs
+++ b/crates/std/src/ffi/mod.rs
@@ -158,27 +158,50 @@
//! [`collect`]: crate::iter::Iterator::collect "iter::Iterator::collect"
//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt "os::windows::ffi::OsStringExt"
//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide "os::windows::ffi::OsStringExt::from_wide"
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "c_str_module", since = "1.88.0")]
pub mod c_str;
+
+#[stable(feature = "core_c_void", since = "1.30.0")]
pub use core::ffi::c_void;
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
pub use core::ffi::{VaArgSafe, VaList};
+#[stable(feature = "core_ffi_c", since = "1.64.0")]
pub use core::ffi::{
c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
c_ulong, c_ulonglong, c_ushort,
};
+#[unstable(feature = "c_size_t", issue = "88345")]
pub use core::ffi::{c_ptrdiff_t, c_size_t, c_ssize_t};
#[doc(inline)]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
pub use self::c_str::FromBytesUntilNulError;
#[doc(inline)]
+#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::FromBytesWithNulError;
#[doc(inline)]
+#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
pub use self::c_str::FromVecWithNulError;
#[doc(inline)]
+#[stable(feature = "cstring_into", since = "1.7.0")]
pub use self::c_str::IntoStringError;
#[doc(inline)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::NulError;
#[doc(inline)]
+#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CStr, CString};
-// #[doc(inline)]
-// pub use self::os_str::{OsStr, OsString};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(inline)]
+pub use self::os_str::{OsStr, OsString};
+
+#[stable(feature = "os_str_display", since = "1.87.0")]
pub mod os_str;
diff --git a/crates/std/src/ffi/os_str.rs b/crates/std/src/ffi/os_str.rs
index 2862f4f..2b1425f 100644
--- a/crates/std/src/ffi/os_str.rs
+++ b/crates/std/src/ffi/os_str.rs
@@ -1,1661 +1,1845 @@
-// //! The [`OsStr`] and [`OsString`] types and associated utilities.
-
-// #[cfg(test)]
-// mod tests;
-
-// use core::clone::CloneToUninit;
-
-// use crate::borrow::{Borrow, Cow};
-// use crate::collections::TryReserveError;
-// use crate::hash::{Hash, Hasher};
-// use crate::ops::{self, Range};
-// use crate::rc::Rc;
-// use crate::str::FromStr;
-// use crate::sync::Arc;
-// use crate::sys::os_str::{Buf, Slice};
-// use crate::sys::{AsInner, FromInner, IntoInner};
-// use crate::{cmp, fmt, slice};
-
-// /// A type that can represent owned, mutable platform-native strings, but is
-// /// cheaply inter-convertible with Rust strings.
-// ///
-// /// The need for this type arises from the fact that:
-// ///
-// /// * On Unix systems, strings are often arbitrary sequences of non-zero
-// /// bytes, in many cases interpreted as UTF-8.
-// ///
-// /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
-// /// values, interpreted as UTF-16 when it is valid to do so.
-// ///
-// /// * In Rust, strings are always valid UTF-8, which may contain zeros.
-// ///
-// /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
-// /// and platform-native string values, and in particular allowing a Rust string
-// /// to be converted into an "OS" string with no cost if possible. A consequence
-// /// of this is that `OsString` instances are *not* `NUL` terminated; in order
-// /// to pass to e.g., Unix system call, you should create a [`CStr`].
-// ///
-// /// `OsString` is to &[OsStr] as [`String`] is to &[str]: the former
-// /// in each pair are owned strings; the latter are borrowed
-// /// references.
-// ///
-// /// Note, `OsString` and [`OsStr`] internally do not necessarily hold strings in
-// /// the form native to the platform; While on Unix, strings are stored as a
-// /// sequence of 8-bit values, on Windows, where strings are 16-bit value based
-// /// as just discussed, strings are also actually stored as a sequence of 8-bit
-// /// values, encoded in a less-strict variant of UTF-8. This is useful to
-// /// understand when handling capacity and length values.
-// ///
-// /// # Capacity of `OsString`
-// ///
-// /// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and
-// /// uses units of bytes in an unspecified encoding for other contents. On a given target, all
-// /// `OsString` and `OsStr` values use the same units for capacity, so the following will work:
-// /// ```
-// /// use std::ffi::{OsStr, OsString};
-// ///
-// /// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
-// /// let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
-// /// ret.push(a); // This will not allocate further
-// /// ret.push(b); // This will not allocate further
-// /// ret
-// /// }
-// /// ```
-// ///
-// /// # Creating an `OsString`
-// ///
-// /// **From a Rust string**: `OsString` implements
-// /// [From]<[String]>, so you can use my_string.[into]\() to
-// /// create an `OsString` from a normal Rust string.
-// ///
-// /// **From slices:** Just like you can start with an empty Rust
-// /// [`String`] and then [`String::push_str`] some &[str]
-// /// sub-string slices into it, you can create an empty `OsString` with
-// /// the [`OsString::new`] method and then push string slices into it with the
-// /// [`OsString::push`] method.
-// ///
-// /// # Extracting a borrowed reference to the whole OS string
-// ///
-// /// You can use the [`OsString::as_os_str`] method to get an &[OsStr] from
-// /// an `OsString`; this is effectively a borrowed reference to the
-// /// whole string.
-// ///
-// /// # Conversions
-// ///
-// /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
-// /// the traits which `OsString` implements for [conversions] from/to native representations.
-// ///
-// /// [`CStr`]: crate::ffi::CStr
-// /// [conversions]: super#conversions
-// /// [into]: Into::into
-// #[cfg_attr(not(test), rustc_diagnostic_item = "OsString")]
-// pub struct OsString {
-// inner: Buf,
-// }
-
-// /// Allows extension traits within `std`.
-// impl crate::sealed::Sealed for OsString {}
-
-// /// Borrowed reference to an OS string (see [`OsString`]).
-// ///
-// /// This type represents a borrowed reference to a string in the operating system's preferred
-// /// representation.
-// ///
-// /// `&OsStr` is to [`OsString`] as &[str] is to [`String`]: the
-// /// former in each pair are borrowed references; the latter are owned strings.
-// ///
-// /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
-// /// the traits which `OsStr` implements for [conversions] from/to native representations.
-// ///
-// /// [conversions]: super#conversions
-// #[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
-// // `OsStr::from_inner` and `impl CloneToUninit for OsStr` current implementation relies
-// // on `OsStr` being layout-compatible with `Slice`.
-// // However, `OsStr` layout is considered an implementation detail and must not be relied upon.
-// #[repr(transparent)]
-// pub struct OsStr {
-// inner: Slice,
-// }
-
-// /// Allows extension traits within `std`.
-// impl crate::sealed::Sealed for OsStr {}
-
-// impl OsString {
-// /// Constructs a new empty `OsString`.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let os_string = OsString::new();
-// /// ```
-// #[must_use]
-// #[inline]
-// pub const fn new() -> OsString {
-// OsString { inner: Buf::from_string(String::new()) }
-// }
-
-// /// Converts bytes to an `OsString` without checking that the bytes contains
-// /// valid [`OsStr`]-encoded data.
-// ///
-// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
-// /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
-// /// ASCII.
-// ///
-// /// See the [module's toplevel documentation about conversions][conversions] for safe,
-// /// cross-platform [conversions] from/to native representations.
-// ///
-// /// # Safety
-// ///
-// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
-// /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
-// /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent
-// /// over the network or stored in a file will likely violate these safety rules.
-// ///
-// /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be
-// /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
-// ///
-// /// # Example
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("Mary had a little lamb");
-// /// let bytes = os_str.as_encoded_bytes();
-// /// let words = bytes.split(|b| *b == b' ');
-// /// let words: Vec<&OsStr> = words.map(|word| {
-// /// // SAFETY:
-// /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes`
-// /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
-// /// unsafe { OsStr::from_encoded_bytes_unchecked(word) }
-// /// }).collect();
-// /// ```
-// ///
-// /// [conversions]: super#conversions
-// #[inline]
-// pub unsafe fn from_encoded_bytes_unchecked(bytes: Vec) -> Self {
-// OsString { inner: unsafe { Buf::from_encoded_bytes_unchecked(bytes) } }
-// }
-
-// /// Converts to an [`OsStr`] slice.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsString, OsStr};
-// ///
-// /// let os_string = OsString::from("foo");
-// /// let os_str = OsStr::new("foo");
-// /// assert_eq!(os_string.as_os_str(), os_str);
-// /// ```
-// #[cfg_attr(not(test), rustc_diagnostic_item = "os_string_as_os_str")]
-// #[must_use]
-// #[inline]
-// pub fn as_os_str(&self) -> &OsStr {
-// self
-// }
-
-// /// Converts the `OsString` into a byte vector. To convert the byte vector back into an
-// /// `OsString`, use the [`OsString::from_encoded_bytes_unchecked`] function.
-// ///
-// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
-// /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
-// /// ASCII.
-// ///
-// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
-// /// be treated as opaque and only comparable within the same Rust version built for the same
-// /// target platform. For example, sending the bytes over the network or storing it in a file
-// /// will likely result in incompatible data. See [`OsString`] for more encoding details
-// /// and [`std::ffi`] for platform-specific, specified conversions.
-// ///
-// /// [`std::ffi`]: crate::ffi
-// #[inline]
-// pub fn into_encoded_bytes(self) -> Vec {
-// self.inner.into_encoded_bytes()
-// }
-
-// /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
-// ///
-// /// On failure, ownership of the original `OsString` is returned.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let os_string = OsString::from("foo");
-// /// let string = os_string.into_string();
-// /// assert_eq!(string, Ok(String::from("foo")));
-// /// ```
-// #[inline]
-// pub fn into_string(self) -> Result {
-// self.inner.into_string().map_err(|buf| OsString { inner: buf })
-// }
-
-// /// Extends the string with the given &[OsStr] slice.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut os_string = OsString::from("foo");
-// /// os_string.push("bar");
-// /// assert_eq!(&os_string, "foobar");
-// /// ```
-// #[inline]
-// pub fn push>(&mut self, s: T) {
-// trait SpecPushTo {
-// fn spec_push_to(&self, buf: &mut OsString);
-// }
-
-// impl> SpecPushTo for T {
-// #[inline]
-// default fn spec_push_to(&self, buf: &mut OsString) {
-// buf.inner.push_slice(&self.as_ref().inner);
-// }
-// }
-
-// // Use a more efficient implementation when the string is UTF-8.
-// macro spec_str($T:ty) {
-// impl SpecPushTo for $T {
-// #[inline]
-// fn spec_push_to(&self, buf: &mut OsString) {
-// buf.inner.push_str(self);
-// }
-// }
-// }
-// spec_str!(str);
-// spec_str!(String);
-
-// s.spec_push_to(self)
-// }
-
-// /// Creates a new `OsString` with at least the given capacity.
-// ///
-// /// The string will be able to hold at least `capacity` length units of other
-// /// OS strings without reallocating. This method is allowed to allocate for
-// /// more units than `capacity`. If `capacity` is 0, the string will not
-// /// allocate.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut os_string = OsString::with_capacity(10);
-// /// let capacity = os_string.capacity();
-// ///
-// /// // This push is done without reallocating
-// /// os_string.push("foo");
-// ///
-// /// assert_eq!(capacity, os_string.capacity());
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn with_capacity(capacity: usize) -> OsString {
-// OsString { inner: Buf::with_capacity(capacity) }
-// }
-
-// /// Truncates the `OsString` to zero length.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut os_string = OsString::from("foo");
-// /// assert_eq!(&os_string, "foo");
-// ///
-// /// os_string.clear();
-// /// assert_eq!(&os_string, "");
-// /// ```
-// #[inline]
-// pub fn clear(&mut self) {
-// self.inner.clear()
-// }
-
-// /// Returns the capacity this `OsString` can hold without reallocating.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let os_string = OsString::with_capacity(10);
-// /// assert!(os_string.capacity() >= 10);
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn capacity(&self) -> usize {
-// self.inner.capacity()
-// }
-
-// /// Reserves capacity for at least `additional` more capacity to be inserted
-// /// in the given `OsString`. Does nothing if the capacity is
-// /// already sufficient.
-// ///
-// /// The collection may reserve more space to speculatively avoid frequent reallocations.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::new();
-// /// s.reserve(10);
-// /// assert!(s.capacity() >= 10);
-// /// ```
-// #[inline]
-// pub fn reserve(&mut self, additional: usize) {
-// self.inner.reserve(additional)
-// }
-
-// /// Tries to reserve capacity for at least `additional` more length units
-// /// in the given `OsString`. The string may reserve more space to speculatively avoid
-// /// frequent reallocations. After calling `try_reserve`, capacity will be
-// /// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
-// /// Does nothing if capacity is already sufficient. This method preserves
-// /// the contents even if an error occurs.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Errors
-// ///
-// /// If the capacity overflows, or the allocator reports a failure, then an error
-// /// is returned.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsStr, OsString};
-// /// use std::collections::TryReserveError;
-// ///
-// /// fn process_data(data: &str) -> Result {
-// /// let mut s = OsString::new();
-// ///
-// /// // Pre-reserve the memory, exiting if we can't
-// /// s.try_reserve(OsStr::new(data).len())?;
-// ///
-// /// // Now we know this can't OOM in the middle of our complex work
-// /// s.push(data);
-// ///
-// /// Ok(s)
-// /// }
-// /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
-// /// ```
-// #[inline]
-// pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
-// self.inner.try_reserve(additional)
-// }
-
-// /// Reserves the minimum capacity for at least `additional` more capacity to
-// /// be inserted in the given `OsString`. Does nothing if the capacity is
-// /// already sufficient.
-// ///
-// /// Note that the allocator may give the collection more space than it
-// /// requests. Therefore, capacity can not be relied upon to be precisely
-// /// minimal. Prefer [`reserve`] if future insertions are expected.
-// ///
-// /// [`reserve`]: OsString::reserve
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::new();
-// /// s.reserve_exact(10);
-// /// assert!(s.capacity() >= 10);
-// /// ```
-// #[inline]
-// pub fn reserve_exact(&mut self, additional: usize) {
-// self.inner.reserve_exact(additional)
-// }
-
-// /// Tries to reserve the minimum capacity for at least `additional`
-// /// more length units in the given `OsString`. After calling
-// /// `try_reserve_exact`, capacity will be greater than or equal to
-// /// `self.len() + additional` if it returns `Ok(())`.
-// /// Does nothing if the capacity is already sufficient.
-// ///
-// /// Note that the allocator may give the `OsString` more space than it
-// /// requests. Therefore, capacity can not be relied upon to be precisely
-// /// minimal. Prefer [`try_reserve`] if future insertions are expected.
-// ///
-// /// [`try_reserve`]: OsString::try_reserve
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Errors
-// ///
-// /// If the capacity overflows, or the allocator reports a failure, then an error
-// /// is returned.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsStr, OsString};
-// /// use std::collections::TryReserveError;
-// ///
-// /// fn process_data(data: &str) -> Result {
-// /// let mut s = OsString::new();
-// ///
-// /// // Pre-reserve the memory, exiting if we can't
-// /// s.try_reserve_exact(OsStr::new(data).len())?;
-// ///
-// /// // Now we know this can't OOM in the middle of our complex work
-// /// s.push(data);
-// ///
-// /// Ok(s)
-// /// }
-// /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
-// /// ```
-// #[inline]
-// pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
-// self.inner.try_reserve_exact(additional)
-// }
-
-// /// Shrinks the capacity of the `OsString` to match its length.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::from("foo");
-// ///
-// /// s.reserve(100);
-// /// assert!(s.capacity() >= 100);
-// ///
-// /// s.shrink_to_fit();
-// /// assert_eq!(3, s.capacity());
-// /// ```
-// #[inline]
-// pub fn shrink_to_fit(&mut self) {
-// self.inner.shrink_to_fit()
-// }
-
-// /// Shrinks the capacity of the `OsString` with a lower bound.
-// ///
-// /// The capacity will remain at least as large as both the length
-// /// and the supplied value.
-// ///
-// /// If the current capacity is less than the lower limit, this is a no-op.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::from("foo");
-// ///
-// /// s.reserve(100);
-// /// assert!(s.capacity() >= 100);
-// ///
-// /// s.shrink_to(10);
-// /// assert!(s.capacity() >= 10);
-// /// s.shrink_to(0);
-// /// assert!(s.capacity() >= 3);
-// /// ```
-// #[inline]
-// pub fn shrink_to(&mut self, min_capacity: usize) {
-// self.inner.shrink_to(min_capacity)
-// }
-
-// /// Converts this `OsString` into a boxed [`OsStr`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsString, OsStr};
-// ///
-// /// let s = OsString::from("hello");
-// ///
-// /// let b: Box = s.into_boxed_os_str();
-// /// ```
-// #[must_use = "`self` will be dropped if the result is not used"]
-// pub fn into_boxed_os_str(self) -> Box {
-// let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
-// unsafe { Box::from_raw(rw) }
-// }
-
-// /// Consumes and leaks the `OsString`, returning a mutable reference to the contents,
-// /// `&'a mut OsStr`.
-// ///
-// /// The caller has free choice over the returned lifetime, including 'static.
-// /// Indeed, this function is ideally used for data that lives for the remainder of
-// /// the program’s life, as dropping the returned reference will cause a memory leak.
-// ///
-// /// It does not reallocate or shrink the `OsString`, so the leaked allocation may include
-// /// unused capacity that is not part of the returned slice. If you want to discard excess
-// /// capacity, call [`into_boxed_os_str`], and then [`Box::leak`] instead.
-// /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
-// ///
-// /// [`into_boxed_os_str`]: Self::into_boxed_os_str
-// #[inline]
-// pub fn leak<'a>(self) -> &'a mut OsStr {
-// OsStr::from_inner_mut(self.inner.leak())
-// }
-
-// /// Truncate the `OsString` to the specified length.
-// ///
-// /// # Panics
-// /// Panics if `len` does not lie on a valid `OsStr` boundary
-// /// (as described in [`OsStr::slice_encoded_bytes`]).
-// #[inline]
-// pub fn truncate(&mut self, len: usize) {
-// self.as_os_str().inner.check_public_boundary(len);
-// // SAFETY: The length was just checked to be at a valid boundary.
-// unsafe { self.inner.truncate_unchecked(len) };
-// }
-
-// /// Provides plumbing to `Vec::extend_from_slice` without giving full
-// /// mutable access to the `Vec`.
-// ///
-// /// # Safety
-// ///
-// /// The slice must be valid for the platform encoding (as described in
-// /// [`OsStr::from_encoded_bytes_unchecked`]).
-// ///
-// /// This bypasses the encoding-dependent surrogate joining, so either
-// /// `self` must not end with a leading surrogate half, or `other` must not
-// /// start with a trailing surrogate half.
-// #[inline]
-// pub(crate) unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
-// // SAFETY: Guaranteed by caller.
-// unsafe { self.inner.extend_from_slice_unchecked(other) };
-// }
-// }
-// impl From for OsString {
-// /// Converts a [`String`] into an [`OsString`].
-// ///
-// /// This conversion does not allocate or copy memory.
-// #[inline]
-// fn from(s: String) -> OsString {
-// OsString { inner: Buf::from_string(s) }
-// }
-// }
-// impl> From<&T> for OsString {
-// /// Copies any value implementing [AsRef]<[OsStr]>
-// /// into a newly allocated [`OsString`].
-// fn from(s: &T) -> OsString {
-// trait SpecToOsString {
-// fn spec_to_os_string(&self) -> OsString;
-// }
-
-// impl> SpecToOsString for T {
-// #[inline]
-// default fn spec_to_os_string(&self) -> OsString {
-// self.as_ref().to_os_string()
-// }
-// }
-
-// // Preserve the known-UTF-8 property for strings.
-// macro spec_str($T:ty) {
-// impl SpecToOsString for $T {
-// #[inline]
-// fn spec_to_os_string(&self) -> OsString {
-// OsString::from(String::from(self))
-// }
-// }
-// }
-// spec_str!(str);
-// spec_str!(String);
-
-// s.spec_to_os_string()
-// }
-// }
-// impl ops::Index for OsString {
-// type Output = OsStr;
-
-// #[inline]
-// fn index(&self, _index: ops::RangeFull) -> &OsStr {
-// OsStr::from_inner(self.inner.as_slice())
-// }
-// }
-// impl ops::IndexMut for OsString {
-// #[inline]
-// fn index_mut(&mut self, _index: ops::RangeFull) -> &mut OsStr {
-// OsStr::from_inner_mut(self.inner.as_mut_slice())
-// }
-// }
-// impl ops::Deref for OsString {
-// type Target = OsStr;
-
-// #[inline]
-// fn deref(&self) -> &OsStr {
-// &self[..]
-// }
-// }
-// impl ops::DerefMut for OsString {
-// #[inline]
-// fn deref_mut(&mut self) -> &mut OsStr {
-// &mut self[..]
-// }
-// }
-// impl Default for OsString {
-// /// Constructs an empty `OsString`.
-// #[inline]
-// fn default() -> OsString {
-// OsString::new()
-// }
-// }
-// impl Clone for OsString {
-// #[inline]
-// fn clone(&self) -> Self {
-// OsString { inner: self.inner.clone() }
-// }
-
-// /// Clones the contents of `source` into `self`.
-// ///
-// /// This method is preferred over simply assigning `source.clone()` to `self`,
-// /// as it avoids reallocation if possible.
-// #[inline]
-// fn clone_from(&mut self, source: &Self) {
-// self.inner.clone_from(&source.inner)
-// }
-// }
-// impl fmt::Debug for OsString {
-// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-// fmt::Debug::fmt(&**self, formatter)
-// }
-// }
-// impl PartialEq for OsString {
-// #[inline]
-// fn eq(&self, other: &OsString) -> bool {
-// &**self == &**other
-// }
-// }
-// impl PartialEq for OsString {
-// #[inline]
-// fn eq(&self, other: &str) -> bool {
-// &**self == other
-// }
-// }
-// impl PartialEq for str {
-// #[inline]
-// fn eq(&self, other: &OsString) -> bool {
-// &**other == self
-// }
-// }
-// impl PartialEq<&str> for OsString {
-// #[inline]
-// fn eq(&self, other: &&str) -> bool {
-// **self == **other
-// }
-// }
-// impl<'a> PartialEq for &'a str {
-// #[inline]
-// fn eq(&self, other: &OsString) -> bool {
-// **other == **self
-// }
-// }
-// impl Eq for OsString {}
-// impl PartialOrd for OsString {
-// #[inline]
-// fn partial_cmp(&self, other: &OsString) -> Option {
-// (&**self).partial_cmp(&**other)
-// }
-// #[inline]
-// fn lt(&self, other: &OsString) -> bool {
-// &**self < &**other
-// }
-// #[inline]
-// fn le(&self, other: &OsString) -> bool {
-// &**self <= &**other
-// }
-// #[inline]
-// fn gt(&self, other: &OsString) -> bool {
-// &**self > &**other
-// }
-// #[inline]
-// fn ge(&self, other: &OsString) -> bool {
-// &**self >= &**other
-// }
-// }
-// impl PartialOrd for OsString {
-// #[inline]
-// fn partial_cmp(&self, other: &str) -> Option {
-// (&**self).partial_cmp(other)
-// }
-// }
-// impl Ord for OsString {
-// #[inline]
-// fn cmp(&self, other: &OsString) -> cmp::Ordering {
-// (&**self).cmp(&**other)
-// }
-// }
-// impl Hash for OsString {
-// #[inline]
-// fn hash(&self, state: &mut H) {
-// (&**self).hash(state)
-// }
-// }
-// impl fmt::Write for OsString {
-// fn write_str(&mut self, s: &str) -> fmt::Result {
-// self.push(s);
-// Ok(())
-// }
-// }
-
-// impl OsStr {
-// /// Coerces into an `OsStr` slice.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// ```
-// #[inline]
-// pub const fn new + ?Sized>(s: &S) -> &OsStr {
-// s.as_ref()
-// }
-
-// /// Converts a slice of bytes to an OS string slice without checking that the string contains
-// /// valid `OsStr`-encoded data.
-// ///
-// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
-// /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
-// /// ASCII.
-// ///
-// /// See the [module's toplevel documentation about conversions][conversions] for safe,
-// /// cross-platform [conversions] from/to native representations.
-// ///
-// /// # Safety
-// ///
-// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
-// /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
-// /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent
-// /// over the network or stored in a file will likely violate these safety rules.
-// ///
-// /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be
-// /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
-// ///
-// /// # Example
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("Mary had a little lamb");
-// /// let bytes = os_str.as_encoded_bytes();
-// /// let words = bytes.split(|b| *b == b' ');
-// /// let words: Vec<&OsStr> = words.map(|word| {
-// /// // SAFETY:
-// /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes`
-// /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
-// /// unsafe { OsStr::from_encoded_bytes_unchecked(word) }
-// /// }).collect();
-// /// ```
-// ///
-// /// [conversions]: super#conversions
-// #[inline]
-// pub unsafe fn from_encoded_bytes_unchecked(bytes: &[u8]) -> &Self {
-// Self::from_inner(unsafe { Slice::from_encoded_bytes_unchecked(bytes) })
-// }
-
-// #[inline]
-// const fn from_inner(inner: &Slice) -> &OsStr {
-// // SAFETY: OsStr is just a wrapper of Slice,
-// // therefore converting &Slice to &OsStr is safe.
-// unsafe { &*(inner as *const Slice as *const OsStr) }
-// }
-
-// #[inline]
-// const fn from_inner_mut(inner: &mut Slice) -> &mut OsStr {
-// // SAFETY: OsStr is just a wrapper of Slice,
-// // therefore converting &mut Slice to &mut OsStr is safe.
-// // Any method that mutates OsStr must be careful not to
-// // break platform-specific encoding, in particular Wtf8 on Windows.
-// unsafe { &mut *(inner as *mut Slice as *mut OsStr) }
-// }
-
-// /// Yields a &[str] slice if the `OsStr` is valid Unicode.
-// ///
-// /// This conversion may entail doing a check for UTF-8 validity.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// assert_eq!(os_str.to_str(), Some("foo"));
-// /// ```
-// #[must_use = "this returns the result of the operation, \
-// without modifying the original"]
-// #[inline]
-// pub fn to_str(&self) -> Option<&str> {
-// self.inner.to_str().ok()
-// }
-
-// /// Converts an `OsStr` to a [Cow]<[str]>.
-// ///
-// /// Any non-UTF-8 sequences are replaced with
-// /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
-// ///
-// /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
-// ///
-// /// # Examples
-// ///
-// /// Calling `to_string_lossy` on an `OsStr` with invalid unicode:
-// ///
-// /// ```
-// /// // Note, due to differences in how Unix and Windows represent strings,
-// /// // we are forced to complicate this example, setting up example `OsStr`s
-// /// // with different source data and via different platform extensions.
-// /// // Understand that in reality you could end up with such example invalid
-// /// // sequences simply through collecting user command line arguments, for
-// /// // example.
-// ///
-// /// #[cfg(unix)] {
-// /// use std::ffi::OsStr;
-// /// use std::os::unix::ffi::OsStrExt;
-// ///
-// /// // Here, the values 0x66 and 0x6f correspond to 'f' and 'o'
-// /// // respectively. The value 0x80 is a lone continuation byte, invalid
-// /// // in a UTF-8 sequence.
-// /// let source = [0x66, 0x6f, 0x80, 0x6f];
-// /// let os_str = OsStr::from_bytes(&source[..]);
-// ///
-// /// assert_eq!(os_str.to_string_lossy(), "fo�o");
-// /// }
-// /// #[cfg(windows)] {
-// /// use std::ffi::OsString;
-// /// use std::os::windows::prelude::*;
-// ///
-// /// // Here the values 0x0066 and 0x006f correspond to 'f' and 'o'
-// /// // respectively. The value 0xD800 is a lone surrogate half, invalid
-// /// // in a UTF-16 sequence.
-// /// let source = [0x0066, 0x006f, 0xD800, 0x006f];
-// /// let os_string = OsString::from_wide(&source[..]);
-// /// let os_str = os_string.as_os_str();
-// ///
-// /// assert_eq!(os_str.to_string_lossy(), "fo�o");
-// /// }
-// /// ```
-// #[must_use = "this returns the result of the operation, \
-// without modifying the original"]
-// #[inline]
-// pub fn to_string_lossy(&self) -> Cow<'_, str> {
-// self.inner.to_string_lossy()
-// }
-
-// /// Copies the slice into an owned [`OsString`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::{OsStr, OsString};
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// let os_string = os_str.to_os_string();
-// /// assert_eq!(os_string, OsString::from("foo"));
-// /// ```
-// #[must_use = "this returns the result of the operation, \
-// without modifying the original"]
-// #[inline]
-// #[cfg_attr(not(test), rustc_diagnostic_item = "os_str_to_os_string")]
-// pub fn to_os_string(&self) -> OsString {
-// OsString { inner: self.inner.to_owned() }
-// }
-
-// /// Checks whether the `OsStr` is empty.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("");
-// /// assert!(os_str.is_empty());
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// assert!(!os_str.is_empty());
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn is_empty(&self) -> bool {
-// self.inner.inner.is_empty()
-// }
-
-// /// Returns the length of this `OsStr`.
-// ///
-// /// Note that this does **not** return the number of bytes in the string in
-// /// OS string form.
-// ///
-// /// The length returned is that of the underlying storage used by `OsStr`.
-// /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr`
-// /// store strings in a form best suited for cheap inter-conversion between
-// /// native-platform and Rust string forms, which may differ significantly
-// /// from both of them, including in storage size and encoding.
-// ///
-// /// This number is simply useful for passing to other methods, like
-// /// [`OsString::with_capacity`] to avoid reallocations.
-// ///
-// /// See the main `OsString` documentation information about encoding and capacity units.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("");
-// /// assert_eq!(os_str.len(), 0);
-// ///
-// /// let os_str = OsStr::new("foo");
-// /// assert_eq!(os_str.len(), 3);
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn len(&self) -> usize {
-// self.inner.inner.len()
-// }
-
-// /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or allocating.
-// #[must_use = "`self` will be dropped if the result is not used"]
-// pub fn into_os_string(self: Box) -> OsString {
-// let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
-// OsString { inner: Buf::from_box(boxed) }
-// }
-
-// /// Converts an OS string slice to a byte slice. To convert the byte slice back into an OS
-// /// string slice, use the [`OsStr::from_encoded_bytes_unchecked`] function.
-// ///
-// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
-// /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
-// /// ASCII.
-// ///
-// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
-// /// be treated as opaque and only comparable within the same Rust version built for the same
-// /// target platform. For example, sending the slice over the network or storing it in a file
-// /// will likely result in incompatible byte slices. See [`OsString`] for more encoding details
-// /// and [`std::ffi`] for platform-specific, specified conversions.
-// ///
-// /// [`std::ffi`]: crate::ffi
-// #[inline]
-// pub fn as_encoded_bytes(&self) -> &[u8] {
-// self.inner.as_encoded_bytes()
-// }
-
-// /// Takes a substring based on a range that corresponds to the return value of
-// /// [`OsStr::as_encoded_bytes`].
-// ///
-// /// The range's start and end must lie on valid `OsStr` boundaries.
-// /// A valid `OsStr` boundary is one of:
-// /// - The start of the string
-// /// - The end of the string
-// /// - Immediately before a valid non-empty UTF-8 substring
-// /// - Immediately after a valid non-empty UTF-8 substring
-// ///
-// /// # Panics
-// ///
-// /// Panics if `range` does not lie on valid `OsStr` boundaries or if it
-// /// exceeds the end of the string.
-// ///
-// /// # Example
-// ///
-// /// ```
-// /// #![feature(os_str_slice)]
-// ///
-// /// use std::ffi::OsStr;
-// ///
-// /// let os_str = OsStr::new("foo=bar");
-// /// let bytes = os_str.as_encoded_bytes();
-// /// if let Some(index) = bytes.iter().position(|b| *b == b'=') {
-// /// let key = os_str.slice_encoded_bytes(..index);
-// /// let value = os_str.slice_encoded_bytes(index + 1..);
-// /// assert_eq!(key, "foo");
-// /// assert_eq!(value, "bar");
-// /// }
-// /// ```
-// pub fn slice_encoded_bytes>(&self, range: R) -> &Self {
-// let encoded_bytes = self.as_encoded_bytes();
-// let Range { start, end } = slice::range(range, ..encoded_bytes.len());
-
-// // `check_public_boundary` should panic if the index does not lie on an
-// // `OsStr` boundary as described above. It's possible to do this in an
-// // encoding-agnostic way, but details of the internal encoding might
-// // permit a more efficient implementation.
-// self.inner.check_public_boundary(start);
-// self.inner.check_public_boundary(end);
-
-// // SAFETY: `slice::range` ensures that `start` and `end` are valid
-// let slice = unsafe { encoded_bytes.get_unchecked(start..end) };
-
-// // SAFETY: `slice` comes from `self` and we validated the boundaries
-// unsafe { Self::from_encoded_bytes_unchecked(slice) }
-// }
-
-// /// Converts this string to its ASCII lower case equivalent in-place.
-// ///
-// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
-// /// but non-ASCII letters are unchanged.
-// ///
-// /// To return a new lowercased value without modifying the existing one, use
-// /// [`OsStr::to_ascii_lowercase`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤");
-// ///
-// /// s.make_ascii_lowercase();
-// ///
-// /// assert_eq!("grÜße, jÜrgen ❤", s);
-// /// ```
-// #[inline]
-// pub fn make_ascii_lowercase(&mut self) {
-// self.inner.make_ascii_lowercase()
-// }
-
-// /// Converts this string to its ASCII upper case equivalent in-place.
-// ///
-// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
-// /// but non-ASCII letters are unchanged.
-// ///
-// /// To return a new uppercased value without modifying the existing one, use
-// /// [`OsStr::to_ascii_uppercase`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let mut s = OsString::from("Grüße, Jürgen ❤");
-// ///
-// /// s.make_ascii_uppercase();
-// ///
-// /// assert_eq!("GRüßE, JüRGEN ❤", s);
-// /// ```
-// #[inline]
-// pub fn make_ascii_uppercase(&mut self) {
-// self.inner.make_ascii_uppercase()
-// }
-
-// /// Returns a copy of this string where each character is mapped to its
-// /// ASCII lower case equivalent.
-// ///
-// /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
-// /// but non-ASCII letters are unchanged.
-// ///
-// /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// /// let s = OsString::from("Grüße, Jürgen ❤");
-// ///
-// /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
-// /// ```
-// #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase`"]
-// pub fn to_ascii_lowercase(&self) -> OsString {
-// OsString::from_inner(self.inner.to_ascii_lowercase())
-// }
-
-// /// Returns a copy of this string where each character is mapped to its
-// /// ASCII upper case equivalent.
-// ///
-// /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
-// /// but non-ASCII letters are unchanged.
-// ///
-// /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`].
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// /// let s = OsString::from("Grüße, Jürgen ❤");
-// ///
-// /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
-// /// ```
-// #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase`"]
-// pub fn to_ascii_uppercase(&self) -> OsString {
-// OsString::from_inner(self.inner.to_ascii_uppercase())
-// }
-
-// /// Checks if all characters in this string are within the ASCII range.
-// ///
-// /// An empty string returns `true`.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// let ascii = OsString::from("hello!\n");
-// /// let non_ascii = OsString::from("Grüße, Jürgen ❤");
-// ///
-// /// assert!(ascii.is_ascii());
-// /// assert!(!non_ascii.is_ascii());
-// /// ```
-// #[must_use]
-// #[inline]
-// pub fn is_ascii(&self) -> bool {
-// self.inner.is_ascii()
-// }
-
-// /// Checks that two strings are an ASCII case-insensitive match.
-// ///
-// /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
-// /// but without allocating and copying temporaries.
-// ///
-// /// # Examples
-// ///
-// /// ```
-// /// use std::ffi::OsString;
-// ///
-// /// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS"));
-// /// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS"));
-// /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS"));
-// /// ```
-// pub fn eq_ignore_ascii_case>(&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
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let s = OsStr::new("Hello, world!");
-// /// println!("{}", s.display());
-// /// ```
-// #[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 }
-// }
-
-// /// Returns the same string as a string slice `&OsStr`.
-// ///
-// /// This method is redundant when used directly on `&OsStr`, but
-// /// it helps dereferencing other string-like types to string slices,
-// /// for example references to `Box` or `Arc`.
-// #[inline]
-// pub const fn as_os_str(&self) -> &OsStr {
-// self
-// }
-// }
-// impl From<&OsStr> for Box {
-// /// Copies the string into a newly allocated [Box]<[OsStr]>.
-// #[inline]
-// fn from(s: &OsStr) -> Box {
-// Box::clone_from_ref(s)
-// }
-// }
-// impl From<&mut OsStr> for Box {
-// /// Copies the string into a newly allocated [Box]<[OsStr]>.
-// #[inline]
-// fn from(s: &mut OsStr) -> Box {
-// Self::from(&*s)
-// }
-// }
-// impl From> for Box {
-// /// Converts a `Cow<'a, OsStr>` into a [Box]<[OsStr]>,
-// /// by copying the contents if they are borrowed.
-// #[inline]
-// fn from(cow: Cow<'_, OsStr>) -> Box {
-// match cow {
-// Cow::Borrowed(s) => Box::from(s),
-// Cow::Owned(s) => Box::from(s),
-// }
-// }
-// }
-// impl From> for OsString {
-// /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or
-// /// allocating.
-// #[inline]
-// fn from(boxed: Box) -> OsString {
-// boxed.into_os_string()
-// }
-// }
-// impl From for Box {
-// /// Converts an [`OsString`] into a [Box]<[OsStr]> without copying or allocating.
-// #[inline]
-// fn from(s: OsString) -> Box {
-// s.into_boxed_os_str()
-// }
-// }
-// impl Clone for Box {
-// #[inline]
-// fn clone(&self) -> Self {
-// self.to_os_string().into_boxed_os_str()
-// }
-// }
-// unsafe impl CloneToUninit for OsStr {
-// #[inline]
-// #[cfg_attr(debug_assertions, track_caller)]
-// unsafe fn clone_to_uninit(&self, dst: *mut u8) {
-// // SAFETY: we're just a transparent wrapper around a platform-specific Slice
-// unsafe { self.inner.clone_to_uninit(dst) }
-// }
-// }
-// impl From for Arc {
-// /// Converts an [`OsString`] into an [Arc]<[OsStr]> by moving the [`OsString`]
-// /// data into a new [`Arc`] buffer.
-// #[inline]
-// fn from(s: OsString) -> Arc {
-// let arc = s.inner.into_arc();
-// unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
-// }
-// }
-// impl From<&OsStr> for Arc {
-// /// Copies the string into a newly allocated [Arc]<[OsStr]>.
-// #[inline]
-// fn from(s: &OsStr) -> Arc {
-// let arc = s.inner.into_arc();
-// unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
-// }
-// }
-// impl From<&mut OsStr> for Arc {
-// /// Copies the string into a newly allocated [Arc]<[OsStr]>.
-// #[inline]
-// fn from(s: &mut OsStr) -> Arc {
-// Arc::from(&*s)
-// }
-// }
-// impl From for Rc {
-// /// Converts an [`OsString`] into an [Rc]<[OsStr]> by moving the [`OsString`]
-// /// data into a new [`Rc`] buffer.
-// #[inline]
-// fn from(s: OsString) -> Rc {
-// let rc = s.inner.into_rc();
-// unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
-// }
-// }
-// impl From<&OsStr> for Rc {
-// /// Copies the string into a newly allocated [Rc]<[OsStr]>.
-// #[inline]
-// fn from(s: &OsStr) -> Rc {
-// let rc = s.inner.into_rc();
-// unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
-// }
-// }
-// impl From<&mut OsStr> for Rc {
-// /// Copies the string into a newly allocated [Rc]<[OsStr]>.
-// #[inline]
-// fn from(s: &mut OsStr) -> Rc {
-// Rc::from(&*s)
-// }
-// }
-// impl<'a> From for Cow<'a, OsStr> {
-// /// Moves the string into a [`Cow::Owned`].
-// #[inline]
-// fn from(s: OsString) -> Cow<'a, OsStr> {
-// Cow::Owned(s)
-// }
-// }
-// impl<'a> From<&'a OsStr> for Cow<'a, OsStr> {
-// /// Converts the string reference into a [`Cow::Borrowed`].
-// #[inline]
-// fn from(s: &'a OsStr) -> Cow<'a, OsStr> {
-// Cow::Borrowed(s)
-// }
-// }
-// impl<'a> From<&'a OsString> for Cow<'a, OsStr> {
-// /// Converts the string reference into a [`Cow::Borrowed`].
-// #[inline]
-// fn from(s: &'a OsString) -> Cow<'a, OsStr> {
-// Cow::Borrowed(s.as_os_str())
-// }
-// }
-// impl<'a> From> for OsString {
-// /// Converts a `Cow<'a, OsStr>` into an [`OsString`],
-// /// by copying the contents if they are borrowed.
-// #[inline]
-// fn from(s: Cow<'a, OsStr>) -> Self {
-// s.into_owned()
-// }
-// }
-// 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()
-// }
-// }
-// impl Default for Box {
-// #[inline]
-// fn default() -> Box {
-// let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
-// unsafe { Box::from_raw(rw) }
-// }
-// }
-// impl Default for &OsStr {
-// /// Creates an empty `OsStr`.
-// #[inline]
-// fn default() -> Self {
-// OsStr::new("")
-// }
-// }
-// impl PartialEq for OsStr {
-// #[inline]
-// fn eq(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().eq(other.as_encoded_bytes())
-// }
-// }
-// impl PartialEq for OsStr {
-// #[inline]
-// fn eq(&self, other: &str) -> bool {
-// *self == *OsStr::new(other)
-// }
-// }
-// impl PartialEq for str {
-// #[inline]
-// fn eq(&self, other: &OsStr) -> bool {
-// *other == *OsStr::new(self)
-// }
-// }
-// impl Eq for OsStr {}
-// impl PartialOrd for OsStr {
-// #[inline]
-// fn partial_cmp(&self, other: &OsStr) -> Option {
-// self.as_encoded_bytes().partial_cmp(other.as_encoded_bytes())
-// }
-// #[inline]
-// fn lt(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().lt(other.as_encoded_bytes())
-// }
-// #[inline]
-// fn le(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().le(other.as_encoded_bytes())
-// }
-// #[inline]
-// fn gt(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().gt(other.as_encoded_bytes())
-// }
-// #[inline]
-// fn ge(&self, other: &OsStr) -> bool {
-// self.as_encoded_bytes().ge(other.as_encoded_bytes())
-// }
-// }
-// impl PartialOrd for OsStr {
-// #[inline]
-// fn partial_cmp(&self, other: &str) -> Option {
-// self.partial_cmp(OsStr::new(other))
-// }
-// }
-
-// // FIXME (#19470): cannot provide PartialOrd for str until we
-// // have more flexible coherence rules.
-// impl Ord for OsStr {
-// #[inline]
-// fn cmp(&self, other: &OsStr) -> cmp::Ordering {
-// self.as_encoded_bytes().cmp(other.as_encoded_bytes())
-// }
-// }
-
-// macro_rules! impl_cmp {
-// ($lhs:ty, $rhs: ty) => {
-// impl PartialEq<$rhs> for $lhs {
-// #[inline]
-// fn eq(&self, other: &$rhs) -> bool {
-// ::eq(self, other)
-// }
-// }
-// impl PartialEq<$lhs> for $rhs {
-// #[inline]
-// fn eq(&self, other: &$lhs) -> bool {
-// ::eq(self, other)
-// }
-// }
-// impl PartialOrd<$rhs> for $lhs {
-// #[inline]
-// fn partial_cmp(&self, other: &$rhs) -> Option {
-// ::partial_cmp(self, other)
-// }
-// }
-// impl PartialOrd<$lhs> for $rhs {
-// #[inline]
-// fn partial_cmp(&self, other: &$lhs) -> Option {
-// ::partial_cmp(self, other)
-// }
-// }
-// };
-// }
-
-// impl_cmp!(OsString, OsStr);
-// impl_cmp!(OsString, &OsStr);
-// impl_cmp!(Cow<'_, OsStr>, OsStr);
-// impl_cmp!(Cow<'_, OsStr>, &OsStr);
-// impl_cmp!(Cow<'_, OsStr>, OsString);
-// impl Hash for OsStr {
-// #[inline]
-// fn hash(&self, state: &mut H) {
-// self.as_encoded_bytes().hash(state)
-// }
-// }
-// impl fmt::Debug for OsStr {
-// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-// fmt::Debug::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
-// ///
-// /// ```
-// /// use std::ffi::OsStr;
-// ///
-// /// let s = OsStr::new("Hello, world!");
-// /// println!("{}", s.display());
-// /// ```
-// ///
-// /// [`Display`]: fmt::Display
-// /// [`format!`]: crate::format
-// pub struct Display<'a> {
-// os_str: &'a OsStr,
-// }
-// impl fmt::Debug for Display<'_> {
-// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-// fmt::Debug::fmt(&self.os_str, f)
-// }
-// }
-// impl fmt::Display for Display<'_> {
-// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-// fmt::Display::fmt(&self.os_str.inner, f)
-// }
-// }
-// impl> alloc::slice::Join<&OsStr> for [S] {
-// type Output = OsString;
-
-// fn join(slice: &Self, sep: &OsStr) -> OsString {
-// let Some((first, suffix)) = slice.split_first() else {
-// return OsString::new();
-// };
-// let first_owned = first.borrow().to_owned();
-// suffix.iter().fold(first_owned, |mut a, b| {
-// a.push(sep);
-// a.push(b.borrow());
-// a
-// })
-// }
-// }
-// impl Borrow for OsString {
-// #[inline]
-// fn borrow(&self) -> &OsStr {
-// &self[..]
-// }
-// }
-// impl ToOwned for OsStr {
-// type Owned = OsString;
-// #[inline]
-// fn to_owned(&self) -> OsString {
-// self.to_os_string()
-// }
-// #[inline]
-// fn clone_into(&self, target: &mut OsString) {
-// self.inner.clone_into(&mut target.inner)
-// }
-// }
-// impl const AsRef for OsStr {
-// #[inline]
-// fn as_ref(&self) -> &OsStr {
-// self
-// }
-// }
-// impl AsRef for OsString {
-// #[inline]
-// fn as_ref(&self) -> &OsStr {
-// self
-// }
-// }
-// impl AsRef for str {
-// #[inline]
-// fn as_ref(&self) -> &OsStr {
-// OsStr::from_inner(Slice::from_str(self))
-// }
-// }
-// impl AsRef for String {
-// #[inline]
-// fn as_ref(&self) -> &OsStr {
-// (&**self).as_ref()
-// }
-// }
-
-// impl FromInner for OsString {
-// #[inline]
-// fn from_inner(buf: Buf) -> OsString {
-// OsString { inner: buf }
-// }
-// }
-
-// impl IntoInner for OsString {
-// #[inline]
-// fn into_inner(self) -> Buf {
-// self.inner
-// }
-// }
-
-// impl AsInner for OsStr {
-// #[inline]
-// fn as_inner(&self) -> &Slice {
-// &self.inner
-// }
-// }
-// impl FromStr for OsString {
-// type Err = core::convert::Infallible;
-
-// #[inline]
-// fn from_str(s: &str) -> Result {
-// Ok(OsString::from(s))
-// }
-// }
-// impl Extend for OsString {
-// #[inline]
-// fn extend>(&mut self, iter: T) {
-// for s in iter {
-// self.push(&s);
-// }
-// }
-// }
-// impl<'a> Extend<&'a OsStr> for OsString {
-// #[inline]
-// fn extend>(&mut self, iter: T) {
-// for s in iter {
-// self.push(s);
-// }
-// }
-// }
-// impl<'a> Extend> for OsString {
-// #[inline]
-// fn extend>>(&mut self, iter: T) {
-// for s in iter {
-// self.push(&s);
-// }
-// }
-// }
-// impl FromIterator for OsString {
-// #[inline]
-// fn from_iter>(iter: I) -> Self {
-// let mut iterator = iter.into_iter();
-
-// // Because we're iterating over `OsString`s, we can avoid at least
-// // one allocation by getting the first string from the iterator
-// // and appending to it all the subsequent strings.
-// match iterator.next() {
-// None => OsString::new(),
-// Some(mut buf) => {
-// buf.extend(iterator);
-// buf
-// }
-// }
-// }
-// }
-// impl<'a> FromIterator<&'a OsStr> for OsString {
-// #[inline]
-// fn from_iter>(iter: I) -> Self {
-// let mut buf = Self::new();
-// for s in iter {
-// buf.push(s);
-// }
-// buf
-// }
-// }
-// impl<'a> FromIterator> for OsString {
-// #[inline]
-// fn from_iter>>(iter: I) -> Self {
-// let mut iterator = iter.into_iter();
-
-// // Because we're iterating over `OsString`s, we can avoid at least
-// // one allocation by getting the first owned string from the iterator
-// // and appending to it all the subsequent strings.
-// match iterator.next() {
-// None => OsString::new(),
-// Some(Cow::Owned(mut buf)) => {
-// buf.extend(iterator);
-// buf
-// }
-// Some(Cow::Borrowed(buf)) => {
-// let mut buf = OsString::from(buf);
-// buf.extend(iterator);
-// buf
-// }
-// }
-// }
-// }
+//! The [`OsStr`] and [`OsString`] types and associated utilities.
+
+#[cfg(test)]
+mod tests;
+
+use core::clone::CloneToUninit;
+
+use crate::borrow::{Borrow, Cow};
+use alloc::collections::TryReserveError;
+use crate::hash::{Hash, Hasher};
+use crate::ops::{self, Range};
+use crate::rc::Rc;
+use crate::str::FromStr;
+use alloc::sync::Arc;
+use crate::sys::os_str::{Buf, Slice};
+use crate::sys::{AsInner, FromInner, IntoInner};
+use crate::{cmp, fmt, slice};
+
+/// A type that can represent owned, mutable platform-native strings, but is
+/// cheaply inter-convertible with Rust strings.
+///
+/// The need for this type arises from the fact that:
+///
+/// * On Unix systems, strings are often arbitrary sequences of non-zero
+/// bytes, in many cases interpreted as UTF-8.
+///
+/// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
+/// values, interpreted as UTF-16 when it is valid to do so.
+///
+/// * In Rust, strings are always valid UTF-8, which may contain zeros.
+///
+/// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
+/// and platform-native string values, and in particular allowing a Rust string
+/// to be converted into an "OS" string with no cost if possible. A consequence
+/// of this is that `OsString` instances are *not* `NUL` terminated; in order
+/// to pass to e.g., Unix system call, you should create a [`CStr`].
+///
+/// `OsString` is to &[OsStr] as [`String`] is to &[str]: the former
+/// in each pair are owned strings; the latter are borrowed
+/// references.
+///
+/// Note, `OsString` and [`OsStr`] internally do not necessarily hold strings in
+/// the form native to the platform; While on Unix, strings are stored as a
+/// sequence of 8-bit values, on Windows, where strings are 16-bit value based
+/// as just discussed, strings are also actually stored as a sequence of 8-bit
+/// values, encoded in a less-strict variant of UTF-8. This is useful to
+/// understand when handling capacity and length values.
+///
+/// # Capacity of `OsString`
+///
+/// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and
+/// uses units of bytes in an unspecified encoding for other contents. On a given target, all
+/// `OsString` and `OsStr` values use the same units for capacity, so the following will work:
+/// ```
+/// use std::ffi::{OsStr, OsString};
+///
+/// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
+/// let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
+/// ret.push(a); // This will not allocate further
+/// ret.push(b); // This will not allocate further
+/// ret
+/// }
+/// ```
+///
+/// # Creating an `OsString`
+///
+/// **From a Rust string**: `OsString` implements
+/// [From]<[String]>, so you can use my_string.[into]\() to
+/// create an `OsString` from a normal Rust string.
+///
+/// **From slices:** Just like you can start with an empty Rust
+/// [`String`] and then [`String::push_str`] some &[str]
+/// sub-string slices into it, you can create an empty `OsString` with
+/// the [`OsString::new`] method and then push string slices into it with the
+/// [`OsString::push`] method.
+///
+/// # Extracting a borrowed reference to the whole OS string
+///
+/// You can use the [`OsString::as_os_str`] method to get an &[OsStr] from
+/// an `OsString`; this is effectively a borrowed reference to the
+/// whole string.
+///
+/// # Conversions
+///
+/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
+/// the traits which `OsString` implements for [conversions] from/to native representations.
+///
+/// [`CStr`]: crate::ffi::CStr
+/// [conversions]: super#conversions
+/// [into]: Into::into
+#[cfg_attr(not(test), rustc_diagnostic_item = "OsString")]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct OsString {
+ inner: Buf,
+}
+
+/// Allows extension traits within `std`.
+#[unstable(feature = "sealed", issue = "none")]
+impl crate::sealed::Sealed for OsString {}
+
+/// Borrowed reference to an OS string (see [`OsString`]).
+///
+/// This type represents a borrowed reference to a string in the operating system's preferred
+/// representation.
+///
+/// `&OsStr` is to [`OsString`] as &[str] is to [`String`]: the
+/// former in each pair are borrowed references; the latter are owned strings.
+///
+/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
+/// the traits which `OsStr` implements for [conversions] from/to native representations.
+///
+/// [conversions]: super#conversions
+#[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
+#[stable(feature = "rust1", since = "1.0.0")]
+// `OsStr::from_inner` and `impl CloneToUninit for OsStr` current implementation relies
+// on `OsStr` being layout-compatible with `Slice`.
+// However, `OsStr` layout is considered an implementation detail and must not be relied upon.
+#[repr(transparent)]
+pub struct OsStr {
+ inner: Slice,
+}
+
+/// Allows extension traits within `std`.
+#[unstable(feature = "sealed", issue = "none")]
+impl crate::sealed::Sealed for OsStr {}
+
+impl OsString {
+ /// Constructs a new empty `OsString`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let os_string = OsString::new();
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use]
+ #[inline]
+ #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "1.91.0")]
+ pub const fn new() -> OsString {
+ OsString { inner: Buf::from_string(String::new()) }
+ }
+
+ /// Converts bytes to an `OsString` without checking that the bytes contains
+ /// valid [`OsStr`]-encoded data.
+ ///
+ /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
+ /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
+ /// ASCII.
+ ///
+ /// See the [module's toplevel documentation about conversions][conversions] for safe,
+ /// cross-platform [conversions] from/to native representations.
+ ///
+ /// # Safety
+ ///
+ /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
+ /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
+ /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent
+ /// over the network or stored in a file will likely violate these safety rules.
+ ///
+ /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be
+ /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("Mary had a little lamb");
+ /// let bytes = os_str.as_encoded_bytes();
+ /// let words = bytes.split(|b| *b == b' ');
+ /// let words: Vec<&OsStr> = words.map(|word| {
+ /// // SAFETY:
+ /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes`
+ /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
+ /// unsafe { OsStr::from_encoded_bytes_unchecked(word) }
+ /// }).collect();
+ /// ```
+ ///
+ /// [conversions]: super#conversions
+ #[inline]
+ #[stable(feature = "os_str_bytes", since = "1.74.0")]
+ pub unsafe fn from_encoded_bytes_unchecked(bytes: Vec) -> Self {
+ OsString { inner: unsafe { Buf::from_encoded_bytes_unchecked(bytes) } }
+ }
+
+ /// Converts to an [`OsStr`] slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::{OsString, OsStr};
+ ///
+ /// let os_string = OsString::from("foo");
+ /// let os_str = OsStr::new("foo");
+ /// assert_eq!(os_string.as_os_str(), os_str);
+ /// ```
+ #[cfg_attr(not(test), rustc_diagnostic_item = "os_string_as_os_str")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use]
+ #[inline]
+ pub fn as_os_str(&self) -> &OsStr {
+ self
+ }
+
+ /// Converts the `OsString` into a byte vector. To convert the byte vector back into an
+ /// `OsString`, use the [`OsString::from_encoded_bytes_unchecked`] function.
+ ///
+ /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
+ /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
+ /// ASCII.
+ ///
+ /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
+ /// be treated as opaque and only comparable within the same Rust version built for the same
+ /// target platform. For example, sending the bytes over the network or storing it in a file
+ /// will likely result in incompatible data. See [`OsString`] for more encoding details
+ /// and [`std::ffi`] for platform-specific, specified conversions.
+ ///
+ /// [`std::ffi`]: crate::ffi
+ #[inline]
+ #[stable(feature = "os_str_bytes", since = "1.74.0")]
+ pub fn into_encoded_bytes(self) -> Vec {
+ self.inner.into_encoded_bytes()
+ }
+
+ /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
+ ///
+ /// On failure, ownership of the original `OsString` is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let os_string = OsString::from("foo");
+ /// let string = os_string.into_string();
+ /// assert_eq!(string, Ok(String::from("foo")));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ pub fn into_string(self) -> Result {
+ self.inner.into_string().map_err(|buf| OsString { inner: buf })
+ }
+
+ /// Extends the string with the given &[OsStr] slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut os_string = OsString::from("foo");
+ /// os_string.push("bar");
+ /// assert_eq!(&os_string, "foobar");
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ #[rustc_confusables("append", "put")]
+ pub fn push>(&mut self, s: T) {
+ trait SpecPushTo {
+ fn spec_push_to(&self, buf: &mut OsString);
+ }
+
+ impl> SpecPushTo for T {
+ #[inline]
+ default fn spec_push_to(&self, buf: &mut OsString) {
+ buf.inner.push_slice(&self.as_ref().inner);
+ }
+ }
+
+ // Use a more efficient implementation when the string is UTF-8.
+ macro spec_str($T:ty) {
+ impl SpecPushTo for $T {
+ #[inline]
+ fn spec_push_to(&self, buf: &mut OsString) {
+ buf.inner.push_str(self);
+ }
+ }
+ }
+ spec_str!(str);
+ spec_str!(String);
+
+ s.spec_push_to(self)
+ }
+
+ /// Creates a new `OsString` with at least the given capacity.
+ ///
+ /// The string will be able to hold at least `capacity` length units of other
+ /// OS strings without reallocating. This method is allowed to allocate for
+ /// more units than `capacity`. If `capacity` is 0, the string will not
+ /// allocate.
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut os_string = OsString::with_capacity(10);
+ /// let capacity = os_string.capacity();
+ ///
+ /// // This push is done without reallocating
+ /// os_string.push("foo");
+ ///
+ /// assert_eq!(capacity, os_string.capacity());
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ #[must_use]
+ #[inline]
+ pub fn with_capacity(capacity: usize) -> OsString {
+ OsString { inner: Buf::with_capacity(capacity) }
+ }
+
+ /// Truncates the `OsString` to zero length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut os_string = OsString::from("foo");
+ /// assert_eq!(&os_string, "foo");
+ ///
+ /// os_string.clear();
+ /// assert_eq!(&os_string, "");
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ #[inline]
+ pub fn clear(&mut self) {
+ self.inner.clear()
+ }
+
+ /// Returns the capacity this `OsString` can hold without reallocating.
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let os_string = OsString::with_capacity(10);
+ /// assert!(os_string.capacity() >= 10);
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ #[must_use]
+ #[inline]
+ pub fn capacity(&self) -> usize {
+ self.inner.capacity()
+ }
+
+ /// Reserves capacity for at least `additional` more capacity to be inserted
+ /// in the given `OsString`. Does nothing if the capacity is
+ /// already sufficient.
+ ///
+ /// The collection may reserve more space to speculatively avoid frequent reallocations.
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut s = OsString::new();
+ /// s.reserve(10);
+ /// assert!(s.capacity() >= 10);
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ #[inline]
+ pub fn reserve(&mut self, additional: usize) {
+ self.inner.reserve(additional)
+ }
+
+ /// Tries to reserve capacity for at least `additional` more length units
+ /// in the given `OsString`. The string may reserve more space to speculatively avoid
+ /// frequent reallocations. After calling `try_reserve`, capacity will be
+ /// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
+ /// Does nothing if capacity is already sufficient. This method preserves
+ /// the contents even if an error occurs.
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::{OsStr, OsString};
+ /// use std::collections::TryReserveError;
+ ///
+ /// fn process_data(data: &str) -> Result {
+ /// let mut s = OsString::new();
+ ///
+ /// // Pre-reserve the memory, exiting if we can't
+ /// s.try_reserve(OsStr::new(data).len())?;
+ ///
+ /// // Now we know this can't OOM in the middle of our complex work
+ /// s.push(data);
+ ///
+ /// Ok(s)
+ /// }
+ /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
+ /// ```
+ #[stable(feature = "try_reserve_2", since = "1.63.0")]
+ #[inline]
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.inner.try_reserve(additional)
+ }
+
+ /// Reserves the minimum capacity for at least `additional` more capacity to
+ /// be inserted in the given `OsString`. Does nothing if the capacity is
+ /// already sufficient.
+ ///
+ /// Note that the allocator may give the collection more space than it
+ /// requests. Therefore, capacity can not be relied upon to be precisely
+ /// minimal. Prefer [`reserve`] if future insertions are expected.
+ ///
+ /// [`reserve`]: OsString::reserve
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut s = OsString::new();
+ /// s.reserve_exact(10);
+ /// assert!(s.capacity() >= 10);
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ #[inline]
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.inner.reserve_exact(additional)
+ }
+
+ /// Tries to reserve the minimum capacity for at least `additional`
+ /// more length units in the given `OsString`. After calling
+ /// `try_reserve_exact`, capacity will be greater than or equal to
+ /// `self.len() + additional` if it returns `Ok(())`.
+ /// Does nothing if the capacity is already sufficient.
+ ///
+ /// Note that the allocator may give the `OsString` more space than it
+ /// requests. Therefore, capacity can not be relied upon to be precisely
+ /// minimal. Prefer [`try_reserve`] if future insertions are expected.
+ ///
+ /// [`try_reserve`]: OsString::try_reserve
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error
+ /// is returned.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::{OsStr, OsString};
+ /// use std::collections::TryReserveError;
+ ///
+ /// fn process_data(data: &str) -> Result {
+ /// let mut s = OsString::new();
+ ///
+ /// // Pre-reserve the memory, exiting if we can't
+ /// s.try_reserve_exact(OsStr::new(data).len())?;
+ ///
+ /// // Now we know this can't OOM in the middle of our complex work
+ /// s.push(data);
+ ///
+ /// Ok(s)
+ /// }
+ /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
+ /// ```
+ #[stable(feature = "try_reserve_2", since = "1.63.0")]
+ #[inline]
+ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.inner.try_reserve_exact(additional)
+ }
+
+ /// Shrinks the capacity of the `OsString` to match its length.
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut s = OsString::from("foo");
+ ///
+ /// s.reserve(100);
+ /// assert!(s.capacity() >= 100);
+ ///
+ /// s.shrink_to_fit();
+ /// assert_eq!(3, s.capacity());
+ /// ```
+ #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
+ #[inline]
+ pub fn shrink_to_fit(&mut self) {
+ self.inner.shrink_to_fit()
+ }
+
+ /// Shrinks the capacity of the `OsString` with a lower bound.
+ ///
+ /// The capacity will remain at least as large as both the length
+ /// and the supplied value.
+ ///
+ /// If the current capacity is less than the lower limit, this is a no-op.
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut s = OsString::from("foo");
+ ///
+ /// s.reserve(100);
+ /// assert!(s.capacity() >= 100);
+ ///
+ /// s.shrink_to(10);
+ /// assert!(s.capacity() >= 10);
+ /// s.shrink_to(0);
+ /// assert!(s.capacity() >= 3);
+ /// ```
+ #[inline]
+ #[stable(feature = "shrink_to", since = "1.56.0")]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ self.inner.shrink_to(min_capacity)
+ }
+
+ /// Converts this `OsString` into a boxed [`OsStr`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::{OsString, OsStr};
+ ///
+ /// let s = OsString::from("hello");
+ ///
+ /// let b: Box = s.into_boxed_os_str();
+ /// ```
+ #[must_use = "`self` will be dropped if the result is not used"]
+ #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
+ pub fn into_boxed_os_str(self) -> Box {
+ let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
+ unsafe { Box::from_raw(rw) }
+ }
+
+ /// Consumes and leaks the `OsString`, returning a mutable reference to the contents,
+ /// `&'a mut OsStr`.
+ ///
+ /// The caller has free choice over the returned lifetime, including 'static.
+ /// Indeed, this function is ideally used for data that lives for the remainder of
+ /// the program’s life, as dropping the returned reference will cause a memory leak.
+ ///
+ /// It does not reallocate or shrink the `OsString`, so the leaked allocation may include
+ /// unused capacity that is not part of the returned slice. If you want to discard excess
+ /// capacity, call [`into_boxed_os_str`], and then [`Box::leak`] instead.
+ /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
+ ///
+ /// [`into_boxed_os_str`]: Self::into_boxed_os_str
+ #[stable(feature = "os_string_pathbuf_leak", since = "1.89.0")]
+ #[inline]
+ pub fn leak<'a>(self) -> &'a mut OsStr {
+ OsStr::from_inner_mut(self.inner.leak())
+ }
+
+ /// Truncate the `OsString` to the specified length.
+ ///
+ /// # Panics
+ /// Panics if `len` does not lie on a valid `OsStr` boundary
+ /// (as described in [`OsStr::slice_encoded_bytes`]).
+ #[inline]
+ #[unstable(feature = "os_string_truncate", issue = "133262")]
+ pub fn truncate(&mut self, len: usize) {
+ self.as_os_str().inner.check_public_boundary(len);
+ // SAFETY: The length was just checked to be at a valid boundary.
+ unsafe { self.inner.truncate_unchecked(len) };
+ }
+
+ /// Provides plumbing to `Vec::extend_from_slice` without giving full
+ /// mutable access to the `Vec`.
+ ///
+ /// # Safety
+ ///
+ /// The slice must be valid for the platform encoding (as described in
+ /// [`OsStr::from_encoded_bytes_unchecked`]).
+ ///
+ /// This bypasses the encoding-dependent surrogate joining, so either
+ /// `self` must not end with a leading surrogate half, or `other` must not
+ /// start with a trailing surrogate half.
+ #[inline]
+ pub(crate) unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
+ // SAFETY: Guaranteed by caller.
+ unsafe { self.inner.extend_from_slice_unchecked(other) };
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl From for OsString {
+ /// Converts a [`String`] into an [`OsString`].
+ ///
+ /// This conversion does not allocate or copy memory.
+ #[inline]
+ fn from(s: String) -> OsString {
+ OsString { inner: Buf::from_string(s) }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl> From<&T> for OsString {
+ /// Copies any value implementing [AsRef]<[OsStr]>
+ /// into a newly allocated [`OsString`].
+ fn from(s: &T) -> OsString {
+ trait SpecToOsString {
+ fn spec_to_os_string(&self) -> OsString;
+ }
+
+ impl> SpecToOsString for T {
+ #[inline]
+ default fn spec_to_os_string(&self) -> OsString {
+ self.as_ref().to_os_string()
+ }
+ }
+
+ // Preserve the known-UTF-8 property for strings.
+ macro spec_str($T:ty) {
+ impl SpecToOsString for $T {
+ #[inline]
+ fn spec_to_os_string(&self) -> OsString {
+ OsString::from(String::from(self))
+ }
+ }
+ }
+ spec_str!(str);
+ spec_str!(String);
+
+ s.spec_to_os_string()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ops::Index for OsString {
+ type Output = OsStr;
+
+ #[inline]
+ fn index(&self, _index: ops::RangeFull) -> &OsStr {
+ OsStr::from_inner(self.inner.as_slice())
+ }
+}
+
+#[stable(feature = "mut_osstr", since = "1.44.0")]
+impl ops::IndexMut for OsString {
+ #[inline]
+ fn index_mut(&mut self, _index: ops::RangeFull) -> &mut OsStr {
+ OsStr::from_inner_mut(self.inner.as_mut_slice())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ops::Deref for OsString {
+ type Target = OsStr;
+
+ #[inline]
+ fn deref(&self) -> &OsStr {
+ &self[..]
+ }
+}
+
+#[stable(feature = "mut_osstr", since = "1.44.0")]
+impl ops::DerefMut for OsString {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut OsStr {
+ &mut self[..]
+ }
+}
+
+#[stable(feature = "osstring_default", since = "1.9.0")]
+impl Default for OsString {
+ /// Constructs an empty `OsString`.
+ #[inline]
+ fn default() -> OsString {
+ OsString::new()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Clone for OsString {
+ #[inline]
+ fn clone(&self) -> Self {
+ OsString { inner: self.inner.clone() }
+ }
+
+ /// Clones the contents of `source` into `self`.
+ ///
+ /// This method is preferred over simply assigning `source.clone()` to `self`,
+ /// as it avoids reallocation if possible.
+ #[inline]
+ fn clone_from(&mut self, source: &Self) {
+ self.inner.clone_from(&source.inner)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for OsString {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&**self, formatter)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for OsString {
+ #[inline]
+ fn eq(&self, other: &OsString) -> bool {
+ &**self == &**other
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for OsString {
+ #[inline]
+ fn eq(&self, other: &str) -> bool {
+ &**self == other
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for str {
+ #[inline]
+ fn eq(&self, other: &OsString) -> bool {
+ &**other == self
+ }
+}
+
+#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
+impl PartialEq<&str> for OsString {
+ #[inline]
+ fn eq(&self, other: &&str) -> bool {
+ **self == **other
+ }
+}
+
+#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
+impl<'a> PartialEq for &'a str {
+ #[inline]
+ fn eq(&self, other: &OsString) -> bool {
+ **other == **self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Eq for OsString {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for OsString {
+ #[inline]
+ fn partial_cmp(&self, other: &OsString) -> Option {
+ (&**self).partial_cmp(&**other)
+ }
+ #[inline]
+ fn lt(&self, other: &OsString) -> bool {
+ &**self < &**other
+ }
+ #[inline]
+ fn le(&self, other: &OsString) -> bool {
+ &**self <= &**other
+ }
+ #[inline]
+ fn gt(&self, other: &OsString) -> bool {
+ &**self > &**other
+ }
+ #[inline]
+ fn ge(&self, other: &OsString) -> bool {
+ &**self >= &**other
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for OsString {
+ #[inline]
+ fn partial_cmp(&self, other: &str) -> Option {
+ (&**self).partial_cmp(other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Ord for OsString {
+ #[inline]
+ fn cmp(&self, other: &OsString) -> cmp::Ordering {
+ (&**self).cmp(&**other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Hash for OsString {
+ #[inline]
+ fn hash(&self, state: &mut H) {
+ (&**self).hash(state)
+ }
+}
+
+#[stable(feature = "os_string_fmt_write", since = "1.64.0")]
+impl fmt::Write for OsString {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ self.push(s);
+ Ok(())
+ }
+}
+
+impl OsStr {
+ /// Coerces into an `OsStr` slice.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+ pub const fn new + ?Sized>(s: &S) -> &OsStr {
+ s.as_ref()
+ }
+
+ /// Converts a slice of bytes to an OS string slice without checking that the string contains
+ /// valid `OsStr`-encoded data.
+ ///
+ /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
+ /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
+ /// ASCII.
+ ///
+ /// See the [module's toplevel documentation about conversions][conversions] for safe,
+ /// cross-platform [conversions] from/to native representations.
+ ///
+ /// # Safety
+ ///
+ /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
+ /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
+ /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent
+ /// over the network or stored in a file will likely violate these safety rules.
+ ///
+ /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be
+ /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("Mary had a little lamb");
+ /// let bytes = os_str.as_encoded_bytes();
+ /// let words = bytes.split(|b| *b == b' ');
+ /// let words: Vec<&OsStr> = words.map(|word| {
+ /// // SAFETY:
+ /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes`
+ /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
+ /// unsafe { OsStr::from_encoded_bytes_unchecked(word) }
+ /// }).collect();
+ /// ```
+ ///
+ /// [conversions]: super#conversions
+ #[inline]
+ #[stable(feature = "os_str_bytes", since = "1.74.0")]
+ pub unsafe fn from_encoded_bytes_unchecked(bytes: &[u8]) -> &Self {
+ Self::from_inner(unsafe { Slice::from_encoded_bytes_unchecked(bytes) })
+ }
+
+ #[inline]
+ #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+ const fn from_inner(inner: &Slice) -> &OsStr {
+ // SAFETY: OsStr is just a wrapper of Slice,
+ // therefore converting &Slice to &OsStr is safe.
+ unsafe { &*(inner as *const Slice as *const OsStr) }
+ }
+
+ #[inline]
+ #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+ const fn from_inner_mut(inner: &mut Slice) -> &mut OsStr {
+ // SAFETY: OsStr is just a wrapper of Slice,
+ // therefore converting &mut Slice to &mut OsStr is safe.
+ // Any method that mutates OsStr must be careful not to
+ // break platform-specific encoding, in particular Wtf8 on Windows.
+ unsafe { &mut *(inner as *mut Slice as *mut OsStr) }
+ }
+
+ /// Yields a &[str] slice if the `OsStr` is valid Unicode.
+ ///
+ /// This conversion may entail doing a check for UTF-8 validity.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// assert_eq!(os_str.to_str(), Some("foo"));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub fn to_str(&self) -> Option<&str> {
+ self.inner.to_str().ok()
+ }
+
+ /// Converts an `OsStr` to a [Cow]<[str]>.
+ ///
+ /// Any non-UTF-8 sequences are replaced with
+ /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
+ ///
+ /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
+ ///
+ /// # Examples
+ ///
+ /// Calling `to_string_lossy` on an `OsStr` with invalid unicode:
+ ///
+ /// ```
+ /// // Note, due to differences in how Unix and Windows represent strings,
+ /// // we are forced to complicate this example, setting up example `OsStr`s
+ /// // with different source data and via different platform extensions.
+ /// // Understand that in reality you could end up with such example invalid
+ /// // sequences simply through collecting user command line arguments, for
+ /// // example.
+ ///
+ /// #[cfg(unix)] {
+ /// use std::ffi::OsStr;
+ /// use std::os::unix::ffi::OsStrExt;
+ ///
+ /// // Here, the values 0x66 and 0x6f correspond to 'f' and 'o'
+ /// // respectively. The value 0x80 is a lone continuation byte, invalid
+ /// // in a UTF-8 sequence.
+ /// let source = [0x66, 0x6f, 0x80, 0x6f];
+ /// let os_str = OsStr::from_bytes(&source[..]);
+ ///
+ /// assert_eq!(os_str.to_string_lossy(), "fo�o");
+ /// }
+ /// #[cfg(windows)] {
+ /// use std::ffi::OsString;
+ /// use std::os::windows::prelude::*;
+ ///
+ /// // Here the values 0x0066 and 0x006f correspond to 'f' and 'o'
+ /// // respectively. The value 0xD800 is a lone surrogate half, invalid
+ /// // in a UTF-16 sequence.
+ /// let source = [0x0066, 0x006f, 0xD800, 0x006f];
+ /// let os_string = OsString::from_wide(&source[..]);
+ /// let os_str = os_string.as_os_str();
+ ///
+ /// assert_eq!(os_str.to_string_lossy(), "fo�o");
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub fn to_string_lossy(&self) -> Cow<'_, str> {
+ self.inner.to_string_lossy()
+ }
+
+ /// Copies the slice into an owned [`OsString`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::{OsStr, OsString};
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// let os_string = os_str.to_os_string();
+ /// assert_eq!(os_string, OsString::from("foo"));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ #[cfg_attr(not(test), rustc_diagnostic_item = "os_str_to_os_string")]
+ pub fn to_os_string(&self) -> OsString {
+ OsString { inner: self.inner.to_owned() }
+ }
+
+ /// Checks whether the `OsStr` is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("");
+ /// assert!(os_str.is_empty());
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// assert!(!os_str.is_empty());
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ #[must_use]
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.inner.inner.is_empty()
+ }
+
+ /// Returns the length of this `OsStr`.
+ ///
+ /// Note that this does **not** return the number of bytes in the string in
+ /// OS string form.
+ ///
+ /// The length returned is that of the underlying storage used by `OsStr`.
+ /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr`
+ /// store strings in a form best suited for cheap inter-conversion between
+ /// native-platform and Rust string forms, which may differ significantly
+ /// from both of them, including in storage size and encoding.
+ ///
+ /// This number is simply useful for passing to other methods, like
+ /// [`OsString::with_capacity`] to avoid reallocations.
+ ///
+ /// See the main `OsString` documentation information about encoding and capacity units.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("");
+ /// assert_eq!(os_str.len(), 0);
+ ///
+ /// let os_str = OsStr::new("foo");
+ /// assert_eq!(os_str.len(), 3);
+ /// ```
+ #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
+ #[must_use]
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.inner.inner.len()
+ }
+
+ /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or allocating.
+ #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
+ #[must_use = "`self` will be dropped if the result is not used"]
+ pub fn into_os_string(self: Box) -> OsString {
+ let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
+ OsString { inner: Buf::from_box(boxed) }
+ }
+
+ /// Converts an OS string slice to a byte slice. To convert the byte slice back into an OS
+ /// string slice, use the [`OsStr::from_encoded_bytes_unchecked`] function.
+ ///
+ /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
+ /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
+ /// ASCII.
+ ///
+ /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
+ /// be treated as opaque and only comparable within the same Rust version built for the same
+ /// target platform. For example, sending the slice over the network or storing it in a file
+ /// will likely result in incompatible byte slices. See [`OsString`] for more encoding details
+ /// and [`std::ffi`] for platform-specific, specified conversions.
+ ///
+ /// [`std::ffi`]: crate::ffi
+ #[inline]
+ #[stable(feature = "os_str_bytes", since = "1.74.0")]
+ pub fn as_encoded_bytes(&self) -> &[u8] {
+ self.inner.as_encoded_bytes()
+ }
+
+ /// Takes a substring based on a range that corresponds to the return value of
+ /// [`OsStr::as_encoded_bytes`].
+ ///
+ /// The range's start and end must lie on valid `OsStr` boundaries.
+ /// A valid `OsStr` boundary is one of:
+ /// - The start of the string
+ /// - The end of the string
+ /// - Immediately before a valid non-empty UTF-8 substring
+ /// - Immediately after a valid non-empty UTF-8 substring
+ ///
+ /// # Panics
+ ///
+ /// Panics if `range` does not lie on valid `OsStr` boundaries or if it
+ /// exceeds the end of the string.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(os_str_slice)]
+ ///
+ /// use std::ffi::OsStr;
+ ///
+ /// let os_str = OsStr::new("foo=bar");
+ /// let bytes = os_str.as_encoded_bytes();
+ /// if let Some(index) = bytes.iter().position(|b| *b == b'=') {
+ /// let key = os_str.slice_encoded_bytes(..index);
+ /// let value = os_str.slice_encoded_bytes(index + 1..);
+ /// assert_eq!(key, "foo");
+ /// assert_eq!(value, "bar");
+ /// }
+ /// ```
+ #[unstable(feature = "os_str_slice", issue = "118485")]
+ pub fn slice_encoded_bytes>(&self, range: R) -> &Self {
+ let encoded_bytes = self.as_encoded_bytes();
+ let Range { start, end } = slice::range(range, ..encoded_bytes.len());
+
+ // `check_public_boundary` should panic if the index does not lie on an
+ // `OsStr` boundary as described above. It's possible to do this in an
+ // encoding-agnostic way, but details of the internal encoding might
+ // permit a more efficient implementation.
+ self.inner.check_public_boundary(start);
+ self.inner.check_public_boundary(end);
+
+ // SAFETY: `slice::range` ensures that `start` and `end` are valid
+ let slice = unsafe { encoded_bytes.get_unchecked(start..end) };
+
+ // SAFETY: `slice` comes from `self` and we validated the boundaries
+ unsafe { Self::from_encoded_bytes_unchecked(slice) }
+ }
+
+ /// Converts this string to its ASCII lower case equivalent in-place.
+ ///
+ /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+ /// but non-ASCII letters are unchanged.
+ ///
+ /// To return a new lowercased value without modifying the existing one, use
+ /// [`OsStr::to_ascii_lowercase`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤");
+ ///
+ /// s.make_ascii_lowercase();
+ ///
+ /// assert_eq!("grÜße, jÜrgen ❤", s);
+ /// ```
+ #[stable(feature = "osstring_ascii", since = "1.53.0")]
+ #[inline]
+ pub fn make_ascii_lowercase(&mut self) {
+ self.inner.make_ascii_lowercase()
+ }
+
+ /// Converts this string to its ASCII upper case equivalent in-place.
+ ///
+ /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+ /// but non-ASCII letters are unchanged.
+ ///
+ /// To return a new uppercased value without modifying the existing one, use
+ /// [`OsStr::to_ascii_uppercase`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let mut s = OsString::from("Grüße, Jürgen ❤");
+ ///
+ /// s.make_ascii_uppercase();
+ ///
+ /// assert_eq!("GRüßE, JüRGEN ❤", s);
+ /// ```
+ #[stable(feature = "osstring_ascii", since = "1.53.0")]
+ #[inline]
+ pub fn make_ascii_uppercase(&mut self) {
+ self.inner.make_ascii_uppercase()
+ }
+
+ /// Returns a copy of this string where each character is mapped to its
+ /// ASCII lower case equivalent.
+ ///
+ /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+ /// but non-ASCII letters are unchanged.
+ ///
+ /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ /// let s = OsString::from("Grüße, Jürgen ❤");
+ ///
+ /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
+ /// ```
+ #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase`"]
+ #[stable(feature = "osstring_ascii", since = "1.53.0")]
+ pub fn to_ascii_lowercase(&self) -> OsString {
+ OsString::from_inner(self.inner.to_ascii_lowercase())
+ }
+
+ /// Returns a copy of this string where each character is mapped to its
+ /// ASCII upper case equivalent.
+ ///
+ /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+ /// but non-ASCII letters are unchanged.
+ ///
+ /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ /// let s = OsString::from("Grüße, Jürgen ❤");
+ ///
+ /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
+ /// ```
+ #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase`"]
+ #[stable(feature = "osstring_ascii", since = "1.53.0")]
+ pub fn to_ascii_uppercase(&self) -> OsString {
+ OsString::from_inner(self.inner.to_ascii_uppercase())
+ }
+
+ /// Checks if all characters in this string are within the ASCII range.
+ ///
+ /// An empty string returns `true`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// let ascii = OsString::from("hello!\n");
+ /// let non_ascii = OsString::from("Grüße, Jürgen ❤");
+ ///
+ /// assert!(ascii.is_ascii());
+ /// assert!(!non_ascii.is_ascii());
+ /// ```
+ #[stable(feature = "osstring_ascii", since = "1.53.0")]
+ #[must_use]
+ #[inline]
+ pub fn is_ascii(&self) -> bool {
+ self.inner.is_ascii()
+ }
+
+ /// Checks that two strings are an ASCII case-insensitive match.
+ ///
+ /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
+ /// but without allocating and copying temporaries.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::ffi::OsString;
+ ///
+ /// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS"));
+ /// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS"));
+ /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS"));
+ /// ```
+ #[stable(feature = "osstring_ascii", since = "1.53.0")]
+ pub fn eq_ignore_ascii_case>(&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
+ ///
+ /// ```
+ /// use std::ffi::OsStr;
+ ///
+ /// let s = OsStr::new("Hello, world!");
+ /// println!("{}", s.display());
+ /// ```
+ #[stable(feature = "os_str_display", since = "1.87.0")]
+ #[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 }
+ }
+
+ /// Returns the same string as a string slice `&OsStr`.
+ ///
+ /// This method is redundant when used directly on `&OsStr`, but
+ /// it helps dereferencing other string-like types to string slices,
+ /// for example references to `Box` or `Arc`.
+ #[inline]
+ #[unstable(feature = "str_as_str", issue = "130366")]
+ pub const fn as_os_str(&self) -> &OsStr {
+ self
+ }
+}
+
+#[stable(feature = "box_from_os_str", since = "1.17.0")]
+impl From<&OsStr> for Box {
+ /// Copies the string into a newly allocated [Box]<[OsStr]>.
+ #[inline]
+ fn from(s: &OsStr) -> Box {
+ Box::clone_from_ref(s)
+ }
+}
+
+#[stable(feature = "box_from_mut_slice", since = "1.84.0")]
+impl From<&mut OsStr> for Box {
+ /// Copies the string into a newly allocated [Box]<[OsStr]>.
+ #[inline]
+ fn from(s: &mut OsStr) -> Box {
+ Self::from(&*s)
+ }
+}
+
+#[stable(feature = "box_from_cow", since = "1.45.0")]
+impl From> for Box {
+ /// Converts a `Cow<'a, OsStr>` into a [Box]<[OsStr]>,
+ /// by copying the contents if they are borrowed.
+ #[inline]
+ fn from(cow: Cow<'_, OsStr>) -> Box {
+ match cow {
+ Cow::Borrowed(s) => Box::from(s),
+ Cow::Owned(s) => Box::from(s),
+ }
+ }
+}
+
+#[stable(feature = "os_string_from_box", since = "1.18.0")]
+impl From> for OsString {
+ /// Converts a [Box]<[OsStr]> into an [`OsString`] without copying or
+ /// allocating.
+ #[inline]
+ fn from(boxed: Box) -> OsString {
+ boxed.into_os_string()
+ }
+}
+
+#[stable(feature = "box_from_os_string", since = "1.20.0")]
+impl From for Box {
+ /// Converts an [`OsString`] into a [Box]<[OsStr]> without copying or allocating.
+ #[inline]
+ fn from(s: OsString) -> Box {
+ s.into_boxed_os_str()
+ }
+}
+
+#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
+impl Clone for Box {
+ #[inline]
+ fn clone(&self) -> Self {
+ self.to_os_string().into_boxed_os_str()
+ }
+}
+
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for OsStr {
+ #[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ // SAFETY: we're just a transparent wrapper around a platform-specific Slice
+ unsafe { self.inner.clone_to_uninit(dst) }
+ }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
+impl From for Arc {
+ /// Converts an [`OsString`] into an [Arc]<[OsStr]> by moving the [`OsString`]
+ /// data into a new [`Arc`] buffer.
+ #[inline]
+ fn from(s: OsString) -> Arc {
+ let arc = s.inner.into_arc();
+ unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
+ }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
+impl From<&OsStr> for Arc {
+ /// Copies the string into a newly allocated [Arc]<[OsStr]>.
+ #[inline]
+ fn from(s: &OsStr) -> Arc {
+ let arc = s.inner.into_arc();
+ unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
+ }
+}
+
+#[stable(feature = "shared_from_mut_slice", since = "1.84.0")]
+impl From<&mut OsStr> for Arc {
+ /// Copies the string into a newly allocated [Arc]<[OsStr]>.
+ #[inline]
+ fn from(s: &mut OsStr) -> Arc {
+ Arc::from(&*s)
+ }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
+impl From for Rc {
+ /// Converts an [`OsString`] into an [Rc]<[OsStr]> by moving the [`OsString`]
+ /// data into a new [`Rc`] buffer.
+ #[inline]
+ fn from(s: OsString) -> Rc {
+ let rc = s.inner.into_rc();
+ unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
+ }
+}
+
+#[stable(feature = "shared_from_slice2", since = "1.24.0")]
+impl From<&OsStr> for Rc {
+ /// Copies the string into a newly allocated [Rc]<[OsStr]>.
+ #[inline]
+ fn from(s: &OsStr) -> Rc {
+ let rc = s.inner.into_rc();
+ unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
+ }
+}
+
+#[stable(feature = "shared_from_mut_slice", since = "1.84.0")]
+impl From<&mut OsStr> for Rc {
+ /// Copies the string into a newly allocated [Rc]<[OsStr]>.
+ #[inline]
+ fn from(s: &mut OsStr) -> Rc {
+ Rc::from(&*s)
+ }
+}
+
+#[stable(feature = "cow_from_osstr", since = "1.28.0")]
+impl<'a> From for Cow<'a, OsStr> {
+ /// Moves the string into a [`Cow::Owned`].
+ #[inline]
+ fn from(s: OsString) -> Cow<'a, OsStr> {
+ Cow::Owned(s)
+ }
+}
+
+#[stable(feature = "cow_from_osstr", since = "1.28.0")]
+impl<'a> From<&'a OsStr> for Cow<'a, OsStr> {
+ /// Converts the string reference into a [`Cow::Borrowed`].
+ #[inline]
+ fn from(s: &'a OsStr) -> Cow<'a, OsStr> {
+ Cow::Borrowed(s)
+ }
+}
+
+#[stable(feature = "cow_from_osstr", since = "1.28.0")]
+impl<'a> From<&'a OsString> for Cow<'a, OsStr> {
+ /// Converts the string reference into a [`Cow::Borrowed`].
+ #[inline]
+ fn from(s: &'a OsString) -> Cow<'a, OsStr> {
+ Cow::Borrowed(s.as_os_str())
+ }
+}
+
+#[stable(feature = "osstring_from_cow_osstr", since = "1.28.0")]
+impl<'a> From> for OsString {
+ /// Converts a `Cow<'a, OsStr>` into an [`OsString`],
+ /// by copying the contents if they are borrowed.
+ #[inline]
+ fn from(s: Cow<'a, OsStr>) -> Self {
+ s.into_owned()
+ }
+}
+
+#[stable(feature = "str_tryfrom_osstr_impl", since = "1.72.0")]
+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]
+ fn default() -> Box {
+ let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
+ unsafe { Box::from_raw(rw) }
+ }
+}
+
+#[stable(feature = "osstring_default", since = "1.9.0")]
+impl Default for &OsStr {
+ /// Creates an empty `OsStr`.
+ #[inline]
+ fn default() -> Self {
+ OsStr::new("")
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for OsStr {
+ #[inline]
+ fn eq(&self, other: &OsStr) -> bool {
+ self.as_encoded_bytes().eq(other.as_encoded_bytes())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for OsStr {
+ #[inline]
+ fn eq(&self, other: &str) -> bool {
+ *self == *OsStr::new(other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialEq for str {
+ #[inline]
+ fn eq(&self, other: &OsStr) -> bool {
+ *other == *OsStr::new(self)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Eq for OsStr {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for OsStr {
+ #[inline]
+ fn partial_cmp(&self, other: &OsStr) -> Option {
+ self.as_encoded_bytes().partial_cmp(other.as_encoded_bytes())
+ }
+ #[inline]
+ fn lt(&self, other: &OsStr) -> bool {
+ self.as_encoded_bytes().lt(other.as_encoded_bytes())
+ }
+ #[inline]
+ fn le(&self, other: &OsStr) -> bool {
+ self.as_encoded_bytes().le(other.as_encoded_bytes())
+ }
+ #[inline]
+ fn gt(&self, other: &OsStr) -> bool {
+ self.as_encoded_bytes().gt(other.as_encoded_bytes())
+ }
+ #[inline]
+ fn ge(&self, other: &OsStr) -> bool {
+ self.as_encoded_bytes().ge(other.as_encoded_bytes())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for OsStr {
+ #[inline]
+ fn partial_cmp(&self, other: &str) -> Option {
+ self.partial_cmp(OsStr::new(other))
+ }
+}
+
+// FIXME (#19470): cannot provide PartialOrd for str until we
+// have more flexible coherence rules.
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Ord for OsStr {
+ #[inline]
+ fn cmp(&self, other: &OsStr) -> cmp::Ordering {
+ self.as_encoded_bytes().cmp(other.as_encoded_bytes())
+ }
+}
+
+macro_rules! impl_cmp {
+ ($lhs:ty, $rhs: ty) => {
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl PartialEq<$rhs> for $lhs {
+ #[inline]
+ fn eq(&self, other: &$rhs) -> bool {
+ ::eq(self, other)
+ }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl PartialEq<$lhs> for $rhs {
+ #[inline]
+ fn eq(&self, other: &$lhs) -> bool {
+ ::eq(self, other)
+ }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl PartialOrd<$rhs> for $lhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$rhs) -> Option {
+ ::partial_cmp(self, other)
+ }
+ }
+
+ #[stable(feature = "cmp_os_str", since = "1.8.0")]
+ impl PartialOrd<$lhs> for $rhs {
+ #[inline]
+ fn partial_cmp(&self, other: &$lhs) -> Option {
+ ::partial_cmp(self, other)
+ }
+ }
+ };
+}
+
+impl_cmp!(OsString, OsStr);
+impl_cmp!(OsString, &OsStr);
+impl_cmp!(Cow<'_, OsStr>, OsStr);
+impl_cmp!(Cow<'_, OsStr>, &OsStr);
+impl_cmp!(Cow<'_, OsStr>, OsString);
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Hash for OsStr {
+ #[inline]
+ fn hash(&self, state: &mut H) {
+ self.as_encoded_bytes().hash(state)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for OsStr {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::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
+///
+/// ```
+/// use std::ffi::OsStr;
+///
+/// let s = OsStr::new("Hello, world!");
+/// println!("{}", s.display());
+/// ```
+///
+/// [`Display`]: fmt::Display
+/// [`format!`]: crate::format
+#[stable(feature = "os_str_display", since = "1.87.0")]
+pub struct Display<'a> {
+ os_str: &'a OsStr,
+}
+
+#[stable(feature = "os_str_display", since = "1.87.0")]
+impl fmt::Debug for Display<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.os_str, f)
+ }
+}
+
+#[stable(feature = "os_str_display", since = "1.87.0")]
+impl fmt::Display for Display<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(&self.os_str.inner, f)
+ }
+}
+
+#[unstable(feature = "slice_concat_ext", issue = "27747")]
+impl> alloc::slice::Join<&OsStr> for [S] {
+ type Output = OsString;
+
+ fn join(slice: &Self, sep: &OsStr) -> OsString {
+ let Some((first, suffix)) = slice.split_first() else {
+ return OsString::new();
+ };
+ let first_owned = first.borrow().to_owned();
+ suffix.iter().fold(first_owned, |mut a, b| {
+ a.push(sep);
+ a.push(b.borrow());
+ a
+ })
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Borrow for OsString {
+ #[inline]
+ fn borrow(&self) -> &OsStr {
+ &self[..]
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ToOwned for OsStr {
+ type Owned = OsString;
+ #[inline]
+ fn to_owned(&self) -> OsString {
+ self.to_os_string()
+ }
+ #[inline]
+ fn clone_into(&self, target: &mut OsString) {
+ self.inner.clone_into(&mut target.inner)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
+impl const AsRef for OsStr {
+ #[inline]
+ fn as_ref(&self) -> &OsStr {
+ self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef for OsString {
+ #[inline]
+ fn as_ref(&self) -> &OsStr {
+ self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef for str {
+ #[inline]
+ fn as_ref(&self) -> &OsStr {
+ OsStr::from_inner(Slice::from_str(self))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef for String {
+ #[inline]
+ fn as_ref(&self) -> &OsStr {
+ (&**self).as_ref()
+ }
+}
+
+impl FromInner for OsString {
+ #[inline]
+ fn from_inner(buf: Buf) -> OsString {
+ OsString { inner: buf }
+ }
+}
+
+impl IntoInner for OsString {
+ #[inline]
+ fn into_inner(self) -> Buf {
+ self.inner
+ }
+}
+
+impl AsInner for OsStr {
+ #[inline]
+ fn as_inner(&self) -> &Slice {
+ &self.inner
+ }
+}
+
+#[stable(feature = "osstring_from_str", since = "1.45.0")]
+impl FromStr for OsString {
+ type Err = core::convert::Infallible;
+
+ #[inline]
+ fn from_str(s: &str) -> Result {
+ Ok(OsString::from(s))
+ }
+}
+
+#[stable(feature = "osstring_extend", since = "1.52.0")]
+impl Extend for OsString {
+ #[inline]
+ fn extend>(&mut self, iter: T) {
+ for s in iter {
+ self.push(&s);
+ }
+ }
+}
+
+#[stable(feature = "osstring_extend", since = "1.52.0")]
+impl<'a> Extend<&'a OsStr> for OsString {
+ #[inline]
+ fn extend>(&mut self, iter: T) {
+ for s in iter {
+ self.push(s);
+ }
+ }
+}
+
+#[stable(feature = "osstring_extend", since = "1.52.0")]
+impl<'a> Extend> for OsString {
+ #[inline]
+ fn extend>>(&mut self, iter: T) {
+ for s in iter {
+ self.push(&s);
+ }
+ }
+}
+
+#[stable(feature = "osstring_extend", since = "1.52.0")]
+impl FromIterator for OsString {
+ #[inline]
+ fn from_iter>(iter: I) -> Self {
+ let mut iterator = iter.into_iter();
+
+ // Because we're iterating over `OsString`s, we can avoid at least
+ // one allocation by getting the first string from the iterator
+ // and appending to it all the subsequent strings.
+ match iterator.next() {
+ None => OsString::new(),
+ Some(mut buf) => {
+ buf.extend(iterator);
+ buf
+ }
+ }
+ }
+}
+
+#[stable(feature = "osstring_extend", since = "1.52.0")]
+impl<'a> FromIterator<&'a OsStr> for OsString {
+ #[inline]
+ fn from_iter>(iter: I) -> Self {
+ let mut buf = Self::new();
+ for s in iter {
+ buf.push(s);
+ }
+ buf
+ }
+}
+
+#[stable(feature = "osstring_extend", since = "1.52.0")]
+impl<'a> FromIterator> for OsString {
+ #[inline]
+ fn from_iter>>(iter: I) -> Self {
+ let mut iterator = iter.into_iter();
+
+ // Because we're iterating over `OsString`s, we can avoid at least
+ // one allocation by getting the first owned string from the iterator
+ // and appending to it all the subsequent strings.
+ match iterator.next() {
+ None => OsString::new(),
+ Some(Cow::Owned(mut buf)) => {
+ buf.extend(iterator);
+ buf
+ }
+ Some(Cow::Borrowed(buf)) => {
+ let mut buf = OsString::from(buf);
+ buf.extend(iterator);
+ buf
+ }
+ }
+ }
+}
diff --git a/crates/std/src/ffi/os_str/tests.rs b/crates/std/src/ffi/os_str/tests.rs
new file mode 100644
index 0000000..3474f0a
--- /dev/null
+++ b/crates/std/src/ffi/os_str/tests.rs
@@ -0,0 +1,311 @@
+use super::*;
+use crate::mem::MaybeUninit;
+use crate::ptr;
+
+#[test]
+fn test_os_string_with_capacity() {
+ let os_string = OsString::with_capacity(0);
+ assert_eq!(0, os_string.inner.into_inner().capacity());
+
+ let os_string = OsString::with_capacity(10);
+ assert_eq!(10, os_string.inner.into_inner().capacity());
+
+ let mut os_string = OsString::with_capacity(0);
+ os_string.push("abc");
+ assert!(os_string.inner.into_inner().capacity() >= 3);
+}
+
+#[test]
+fn test_os_string_clear() {
+ let mut os_string = OsString::from("abc");
+ assert_eq!(3, os_string.inner.as_inner().len());
+
+ os_string.clear();
+ assert_eq!(&os_string, "");
+ assert_eq!(0, os_string.inner.as_inner().len());
+}
+
+#[test]
+fn test_os_string_leak() {
+ let os_string = OsString::from("have a cake");
+ let (len, cap) = (os_string.len(), os_string.capacity());
+ let leaked = os_string.leak();
+ assert_eq!(leaked.as_encoded_bytes(), b"have a cake");
+ unsafe { drop(String::from_raw_parts(leaked as *mut OsStr as _, len, cap)) }
+}
+
+#[test]
+fn test_os_string_capacity() {
+ let os_string = OsString::with_capacity(0);
+ assert_eq!(0, os_string.capacity());
+
+ let os_string = OsString::with_capacity(10);
+ assert_eq!(10, os_string.capacity());
+
+ let mut os_string = OsString::with_capacity(0);
+ os_string.push("abc");
+ assert!(os_string.capacity() >= 3);
+}
+
+#[test]
+fn test_os_string_reserve() {
+ let mut os_string = OsString::new();
+ assert_eq!(os_string.capacity(), 0);
+
+ os_string.reserve(2);
+ assert!(os_string.capacity() >= 2);
+
+ for _ in 0..16 {
+ os_string.push("a");
+ }
+
+ assert!(os_string.capacity() >= 16);
+ os_string.reserve(16);
+ assert!(os_string.capacity() >= 32);
+
+ os_string.push("a");
+
+ os_string.reserve(16);
+ assert!(os_string.capacity() >= 33)
+}
+
+#[test]
+fn test_os_string_reserve_exact() {
+ let mut os_string = OsString::new();
+ assert_eq!(os_string.capacity(), 0);
+
+ os_string.reserve_exact(2);
+ assert!(os_string.capacity() >= 2);
+
+ for _ in 0..16 {
+ os_string.push("a");
+ }
+
+ assert!(os_string.capacity() >= 16);
+ os_string.reserve_exact(16);
+ assert!(os_string.capacity() >= 32);
+
+ os_string.push("a");
+
+ os_string.reserve_exact(16);
+ assert!(os_string.capacity() >= 33)
+}
+
+#[test]
+fn test_os_string_join() {
+ let strings = [OsStr::new("hello"), OsStr::new("dear"), OsStr::new("world")];
+ assert_eq!("hello", strings[..1].join(OsStr::new(" ")));
+ assert_eq!("hello dear world", strings.join(OsStr::new(" ")));
+ assert_eq!("hellodearworld", strings.join(OsStr::new("")));
+ assert_eq!("hello.\n dear.\n world", strings.join(OsStr::new(".\n ")));
+
+ assert_eq!("dear world", strings[1..].join(&OsString::from(" ")));
+
+ let strings_abc = [OsString::from("a"), OsString::from("b"), OsString::from("c")];
+ assert_eq!("a b c", strings_abc.join(OsStr::new(" ")));
+}
+
+#[test]
+fn test_os_string_default() {
+ let os_string: OsString = Default::default();
+ assert_eq!("", &os_string);
+}
+
+#[test]
+fn test_os_str_is_empty() {
+ let mut os_string = OsString::new();
+ assert!(os_string.is_empty());
+
+ os_string.push("abc");
+ assert!(!os_string.is_empty());
+
+ os_string.clear();
+ assert!(os_string.is_empty());
+}
+
+#[test]
+fn test_os_str_len() {
+ let mut os_string = OsString::new();
+ assert_eq!(0, os_string.len());
+
+ os_string.push("abc");
+ assert_eq!(3, os_string.len());
+
+ os_string.clear();
+ assert_eq!(0, os_string.len());
+}
+
+#[test]
+fn test_os_str_default() {
+ let os_str: &OsStr = Default::default();
+ assert_eq!("", os_str);
+}
+
+#[test]
+fn into_boxed() {
+ let orig = "Hello, world!";
+ let os_str = OsStr::new(orig);
+ let boxed: Box = Box::from(os_str);
+ let os_string = os_str.to_owned().into_boxed_os_str().into_os_string();
+ assert_eq!(os_str, &*boxed);
+ assert_eq!(&*boxed, &*os_string);
+ assert_eq!(&*os_string, os_str);
+}
+
+#[test]
+fn boxed_default() {
+ let boxed = >::default();
+ assert!(boxed.is_empty());
+}
+
+#[test]
+fn test_os_str_clone_into() {
+ let mut os_string = OsString::with_capacity(123);
+ os_string.push("hello");
+ let os_str = OsStr::new("bonjour");
+ os_str.clone_into(&mut os_string);
+ assert_eq!(os_str, os_string);
+ assert!(os_string.capacity() >= 123);
+}
+
+#[test]
+fn into_rc() {
+ let orig = "Hello, world!";
+ let os_str = OsStr::new(orig);
+ let rc: Rc = Rc::from(os_str);
+ let arc: Arc = Arc::from(os_str);
+
+ assert_eq!(&*rc, os_str);
+ assert_eq!(&*arc, os_str);
+
+ let rc2: Rc = Rc::from(os_str.to_owned());
+ let arc2: Arc = Arc::from(os_str.to_owned());
+
+ assert_eq!(&*rc2, os_str);
+ assert_eq!(&*arc2, os_str);
+}
+
+#[test]
+fn slice_encoded_bytes() {
+ let os_str = OsStr::new("123θგ🦀");
+ // ASCII
+ let digits = os_str.slice_encoded_bytes(..3);
+ assert_eq!(digits, "123");
+ let three = os_str.slice_encoded_bytes(2..3);
+ assert_eq!(three, "3");
+ // 2-byte UTF-8
+ let theta = os_str.slice_encoded_bytes(3..5);
+ assert_eq!(theta, "θ");
+ // 3-byte UTF-8
+ let gani = os_str.slice_encoded_bytes(5..8);
+ assert_eq!(gani, "გ");
+ // 4-byte UTF-8
+ let crab = os_str.slice_encoded_bytes(8..);
+ assert_eq!(crab, "🦀");
+}
+
+#[test]
+#[should_panic]
+fn slice_out_of_bounds() {
+ let crab = OsStr::new("🦀");
+ let _ = crab.slice_encoded_bytes(..5);
+}
+
+#[test]
+#[should_panic]
+fn slice_mid_char() {
+ let crab = OsStr::new("🦀");
+ let _ = crab.slice_encoded_bytes(..2);
+}
+
+#[cfg(unix)]
+#[test]
+#[should_panic(expected = "byte index 1 is not an OsStr boundary")]
+fn slice_invalid_data() {
+ use crate::os::unix::ffi::OsStrExt;
+
+ let os_string = OsStr::from_bytes(b"\xFF\xFF");
+ let _ = os_string.slice_encoded_bytes(1..);
+}
+
+#[cfg(unix)]
+#[test]
+#[should_panic(expected = "byte index 1 is not an OsStr boundary")]
+fn slice_partial_utf8() {
+ use crate::os::unix::ffi::{OsStrExt, OsStringExt};
+
+ let part_crab = OsStr::from_bytes(&"🦀".as_bytes()[..3]);
+ let mut os_string = OsString::from_vec(vec![0xFF]);
+ os_string.push(part_crab);
+ let _ = os_string.slice_encoded_bytes(1..);
+}
+
+#[cfg(unix)]
+#[test]
+fn slice_invalid_edge() {
+ use crate::os::unix::ffi::{OsStrExt, OsStringExt};
+
+ let os_string = OsStr::from_bytes(b"a\xFFa");
+ assert_eq!(os_string.slice_encoded_bytes(..1), "a");
+ assert_eq!(os_string.slice_encoded_bytes(1..), OsStr::from_bytes(b"\xFFa"));
+ assert_eq!(os_string.slice_encoded_bytes(..2), OsStr::from_bytes(b"a\xFF"));
+ assert_eq!(os_string.slice_encoded_bytes(2..), "a");
+
+ let os_string = OsStr::from_bytes(&"abc🦀".as_bytes()[..6]);
+ assert_eq!(os_string.slice_encoded_bytes(..3), "abc");
+ assert_eq!(os_string.slice_encoded_bytes(3..), OsStr::from_bytes(b"\xF0\x9F\xA6"));
+
+ let mut os_string = OsString::from_vec(vec![0xFF]);
+ os_string.push("🦀");
+ assert_eq!(os_string.slice_encoded_bytes(..1), OsStr::from_bytes(b"\xFF"));
+ assert_eq!(os_string.slice_encoded_bytes(1..), "🦀");
+}
+
+#[cfg(windows)]
+#[test]
+#[should_panic(expected = "byte index 3 lies between surrogate codepoints")]
+fn slice_between_surrogates() {
+ use crate::os::windows::ffi::OsStringExt;
+
+ let os_string = OsString::from_wide(&[0xD800, 0xD800]);
+ assert_eq!(os_string.as_encoded_bytes(), &[0xED, 0xA0, 0x80, 0xED, 0xA0, 0x80]);
+ let _ = os_string.slice_encoded_bytes(..3);
+}
+
+#[cfg(windows)]
+#[test]
+fn slice_surrogate_edge() {
+ use crate::os::windows::ffi::OsStringExt;
+
+ let surrogate = OsString::from_wide(&[0xD800]);
+ let mut pre_crab = surrogate.clone();
+ pre_crab.push("🦀");
+ assert_eq!(pre_crab.slice_encoded_bytes(..3), surrogate);
+ assert_eq!(pre_crab.slice_encoded_bytes(3..), "🦀");
+
+ let mut post_crab = OsString::from("🦀");
+ post_crab.push(&surrogate);
+ assert_eq!(post_crab.slice_encoded_bytes(..4), "🦀");
+ assert_eq!(post_crab.slice_encoded_bytes(4..), surrogate);
+}
+
+#[test]
+fn clone_to_uninit() {
+ let a = OsStr::new("hello.txt");
+
+ let mut storage = vec![MaybeUninit::::uninit(); size_of_val::(a)];
+ unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
+ assert_eq!(a.as_encoded_bytes(), unsafe { storage.assume_init_ref() });
+
+ let mut b: Box = OsStr::new("world.exe").into();
+ assert_eq!(size_of_val::(a), size_of_val::(&b));
+ assert_ne!(a, &*b);
+ unsafe { a.clone_to_uninit(ptr::from_mut::(&mut b).cast()) };
+ assert_eq!(a, &*b);
+}
+
+#[test]
+fn debug() {
+ let s = "'single quotes'";
+ assert_eq!(format!("{:?}", OsStr::new(s)), format!("{:?}", s));
+}
diff --git a/crates/std/src/hash/mod.rs b/crates/std/src/hash/mod.rs
new file mode 100644
index 0000000..e88f5cb
--- /dev/null
+++ b/crates/std/src/hash/mod.rs
@@ -0,0 +1,91 @@
+//! Generic hashing support.
+//!
+//! This module provides a generic way to compute the [hash] of a value.
+//! Hashes are most commonly used with [`HashMap`] and [`HashSet`].
+//!
+//! [hash]: https://en.wikipedia.org/wiki/Hash_function
+//! [`HashMap`]: ../../std/collections/struct.HashMap.html
+//! [`HashSet`]: ../../std/collections/struct.HashSet.html
+//!
+//! The simplest way to make a type hashable is to use `#[derive(Hash)]`:
+//!
+//! # Examples
+//!
+//! ```rust
+//! use std::hash::{DefaultHasher, Hash, Hasher};
+//!
+//! #[derive(Hash)]
+//! struct Person {
+//! id: u32,
+//! name: String,
+//! phone: u64,
+//! }
+//!
+//! let person1 = Person {
+//! id: 5,
+//! name: "Janet".to_string(),
+//! phone: 555_666_7777,
+//! };
+//! let person2 = Person {
+//! id: 5,
+//! name: "Bob".to_string(),
+//! phone: 555_666_7777,
+//! };
+//!
+//! assert!(calculate_hash(&person1) != calculate_hash(&person2));
+//!
+//! fn calculate_hash(t: &T) -> u64 {
+//! let mut s = DefaultHasher::new();
+//! t.hash(&mut s);
+//! s.finish()
+//! }
+//! ```
+//!
+//! If you need more control over how a value is hashed, you need to implement
+//! the [`Hash`] trait:
+//!
+//! ```rust
+//! use std::hash::{DefaultHasher, Hash, Hasher};
+//!
+//! struct Person {
+//! id: u32,
+//! # #[allow(dead_code)]
+//! name: String,
+//! phone: u64,
+//! }
+//!
+//! impl Hash for Person {
+//! fn hash(&self, state: &mut H) {
+//! self.id.hash(state);
+//! self.phone.hash(state);
+//! }
+//! }
+//!
+//! let person1 = Person {
+//! id: 5,
+//! name: "Janet".to_string(),
+//! phone: 555_666_7777,
+//! };
+//! let person2 = Person {
+//! id: 5,
+//! name: "Bob".to_string(),
+//! phone: 555_666_7777,
+//! };
+//!
+//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2));
+//!
+//! fn calculate_hash(t: &T) -> u64 {
+//! let mut s = DefaultHasher::new();
+//! t.hash(&mut s);
+//! s.finish()
+//! }
+//! ```
+// #![stable(feature = "rust1", since = "1.0.0")]
+
+// pub(crate) mod random;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::hash::*;
+
+// #[stable(feature = "std_hash_exports", since = "1.76.0")]
+// pub use self::random::{DefaultHasher, RandomState};
diff --git a/crates/std/src/io.rs b/crates/std/src/io.rs
index 709f22d..74e35a2 100644
--- a/crates/std/src/io.rs
+++ b/crates/std/src/io.rs
@@ -12,7 +12,7 @@ impl IoBase for Stdin {
}
impl Read for Stdin {
- fn read(&mut self, buf: &mut [u8]) -> Result {
+ fn read(&mut self, buf: &mut [u8]) -> core::result::Result {
unsafe { File::from_raw_fd(0).read(buf) }
}
}
@@ -20,3 +20,20 @@ impl Read for Stdin {
pub fn stdin() -> Stdin {
Stdin
}
+
+pub type Result = core::result::Result;
+
+pub(super) struct Repr();
+
+// Part took from the real std
+#[rustc_macro_transparency = "semiopaque"]
+#[unstable(feature = "io_const_error", issue = "133448")]
+#[allow_internal_unstable(hint_must_use, io_const_error_internals)]
+pub macro const_error($kind:expr, $message:expr $(,)?) {
+ ()
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Error {
+ repr: Repr,
+}
diff --git a/crates/std/src/lib.rs b/crates/std/src/lib.rs
index 871b601..c3d17ee 100644
--- a/crates/std/src/lib.rs
+++ b/crates/std/src/lib.rs
@@ -1,5 +1,34 @@
+#![unstable(feature = "custom_std", issue = "none")]
#![no_std]
+//
+// Lints:
+#![warn(deprecated_in_future)]
+// #![warn(missing_docs)]
+// #![warn(missing_debug_implementations)]
+#![allow(explicit_outlives_requirements)]
+#![allow(unused_lifetimes)]
#![allow(internal_features)]
+#![deny(fuzzy_provenance_casts)]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![allow(rustdoc::redundant_explicit_links)]
+#![warn(rustdoc::unescaped_backticks)]
+// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
+#![deny(ffi_unwind_calls)]
+// std may use features in a platform-specific way
+#![allow(unused_features)]
+//
+// Features:
+#![cfg_attr(
+ test,
+ feature(internal_output_capture, print_internals, update_panic_count, rt)
+)]
+#![cfg_attr(
+ all(target_vendor = "fortanix", target_env = "sgx"),
+ feature(slice_index_methods, coerce_unsized, sgx_platform)
+)]
+#![cfg_attr(all(test, target_os = "uefi"), feature(uefi_std))]
+#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))]
+#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
//
// Language features:
// tidy-alphabetical-start
@@ -44,7 +73,7 @@
#![feature(prelude_import)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
-// #![feature(staged_api)]
+#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(strict_provenance_lints)]
#![feature(thread_local)]
@@ -149,12 +178,14 @@
//
// Only for const-ness:
// tidy-alphabetical-start
-// #![feature(io_const_error)]
+#![feature(io_const_error)]
// tidy-alphabetical-end
//
+
#![feature(c_size_t, unsafe_binders)]
-#![allow(clippy::doc_lazy_continuation, clippy::legacy_numeric_constants)]
+#![allow(clippy::doc_lazy_continuation, clippy::all)]
#![allow(stable_features, incomplete_features)]
+#![allow(unused)]
extern crate alloc;
@@ -216,9 +247,24 @@ pub use alloc::string;
pub use alloc::vec;
pub mod ffi;
+pub mod hash;
pub mod io;
pub mod prelude;
pub mod process;
+pub mod sys;
+
+#[prelude_import]
+#[allow(unused_imports)]
+pub use prelude::rust_2024::*;
+
+#[allow(unused)]
+mod sealed {
+ /// This trait being unreachable from outside the crate
+ /// prevents outside implementations of our extension traits.
+ /// This allows adding more trait methods in the future.
+ #[unstable(feature = "sealed", issue = "none")]
+ pub trait Sealed {}
+}
pub use shared::fs;
pub use shared::syscall;
diff --git a/crates/std/src/prelude.rs b/crates/std/src/prelude.rs
index 895a601..98f8d01 100644
--- a/crates/std/src/prelude.rs
+++ b/crates/std/src/prelude.rs
@@ -1,11 +1,134 @@
pub mod rust_2024 {
pub use crate::print;
pub use crate::println;
- pub use alloc::borrow::ToOwned;
pub use alloc::format;
- pub use alloc::string::String;
pub use alloc::vec;
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(no_inline)]
+ pub use crate::borrow::ToOwned;
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(no_inline)]
+ pub use crate::boxed::Box;
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(no_inline)]
+ pub use crate::string::{String, ToString};
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(no_inline)]
+ pub use crate::vec::Vec;
+
+ // Re-exported built-in macros and traits
+ #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+ #[doc(no_inline)]
+ #[expect(deprecated)]
+ pub use core::prelude::v1::{
+ Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd, assert, assert_eq,
+ assert_ne, cfg, column, compile_error, concat, debug_assert, debug_assert_eq,
+ debug_assert_ne, env, file, format_args, include, include_bytes, include_str, line,
+ matches, module_path, option_env, stringify, todo, r#try, unimplemented, unreachable,
+ write, writeln,
+ };
+
+ #[stable(feature = "cfg_select", since = "1.95.0")]
+ #[doc(no_inline)]
+ pub use core::prelude::v1::cfg_select;
+
+ #[unstable(
+ feature = "concat_bytes",
+ issue = "87555",
+ reason = "`concat_bytes` is not stable enough for use and is subject to change"
+ )]
+ #[doc(no_inline)]
+ pub use core::prelude::v1::concat_bytes;
+
+ #[unstable(feature = "const_format_args", issue = "none")]
+ #[doc(no_inline)]
+ pub use core::prelude::v1::const_format_args;
+
+ #[unstable(
+ feature = "log_syntax",
+ issue = "29598",
+ reason = "`log_syntax!` is not stable enough for use and is subject to change"
+ )]
+ #[doc(no_inline)]
+ pub use core::prelude::v1::log_syntax;
+
+ #[unstable(
+ feature = "trace_macros",
+ issue = "29598",
+ reason = "`trace_macros` is not stable enough for use and is subject to change"
+ )]
+ #[doc(no_inline)]
+ pub use core::prelude::v1::trace_macros;
+
+ // Do not `doc(no_inline)` so that they become doc items on their own
+ // (no public module for them to be re-exported from).
+ #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
+ pub use core::prelude::v1::{
+ alloc_error_handler, bench, derive, global_allocator, test, test_case,
+ };
+
+ #[unstable(feature = "derive_const", issue = "118304")]
+ pub use core::prelude::v1::derive_const;
+
+ // Do not `doc(no_inline)` either.
+ #[unstable(
+ feature = "cfg_accessible",
+ issue = "64797",
+ reason = "`cfg_accessible` is not fully implemented"
+ )]
+ pub use core::prelude::v1::cfg_accessible;
+
+ // Do not `doc(no_inline)` either.
+ #[unstable(
+ feature = "cfg_eval",
+ issue = "82679",
+ reason = "`cfg_eval` is a recently implemented feature"
+ )]
+ pub use core::prelude::v1::cfg_eval;
+
+ // Do not `doc(no_inline)` either.
+ #[unstable(
+ feature = "type_ascription",
+ issue = "23416",
+ reason = "placeholder syntax for type ascription"
+ )]
+ pub use core::prelude::v1::type_ascribe;
+
+ // Do not `doc(no_inline)` either.
+ #[unstable(
+ feature = "deref_patterns",
+ issue = "87121",
+ reason = "placeholder syntax for deref patterns"
+ )]
+ pub use core::prelude::v1::deref;
+
+ // Do not `doc(no_inline)` either.
+ #[unstable(
+ feature = "type_alias_impl_trait",
+ issue = "63063",
+ reason = "`type_alias_impl_trait` has open design concerns"
+ )]
+ pub use core::prelude::v1::define_opaque;
+
+ #[unstable(feature = "extern_item_impls", issue = "125418")]
+ pub use core::prelude::v1::{eii, unsafe_eii};
+
+ #[unstable(feature = "eii_internals", issue = "none")]
+ pub use core::prelude::v1::eii_declaration;
+
+ #[stable(feature = "prelude_2021", since = "1.55.0")]
+ #[doc(no_inline)]
+ pub use core::prelude::rust_2021::*;
+
+ #[stable(feature = "prelude_2024", since = "1.85.0")]
+ #[doc(no_inline)]
+ pub use core::prelude::rust_2024::*;
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(no_inline)]
+ pub use crate::convert::{AsMut, AsRef, From, Into};
+
extern crate alloc;
struct GlobalAllocator;
diff --git a/crates/std/src/sys/env/mod.rs b/crates/std/src/sys/env/mod.rs
new file mode 100644
index 0000000..8985651
--- /dev/null
+++ b/crates/std/src/sys/env/mod.rs
@@ -0,0 +1,62 @@
+//! Platform-dependent environment variables abstraction.
+
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+#[cfg(any(
+ target_family = "unix",
+ target_os = "hermit",
+ target_os = "motor",
+ all(target_vendor = "fortanix", target_env = "sgx"),
+ target_os = "solid_asp3",
+ target_os = "uefi",
+ target_os = "wasi",
+ target_os = "xous",
+))]
+mod common;
+
+cfg_select! {
+ target_family = "unix" => {
+ mod unix;
+ pub use unix::*;
+ }
+ target_family = "windows" => {
+ mod windows;
+ pub use windows::*;
+ }
+ target_os = "hermit" => {
+ mod hermit;
+ pub use hermit::*;
+ }
+ target_os = "motor" => {
+ mod motor;
+ pub use motor::*;
+ }
+ all(target_vendor = "fortanix", target_env = "sgx") => {
+ mod sgx;
+ pub use sgx::*;
+ }
+ target_os = "solid_asp3" => {
+ mod solid;
+ pub use solid::*;
+ }
+ target_os = "uefi" => {
+ mod uefi;
+ pub use uefi::*;
+ }
+ target_os = "wasi" => {
+ mod wasi;
+ pub use wasi::*;
+ }
+ target_os = "xous" => {
+ mod xous;
+ pub use xous::*;
+ }
+ target_os = "zkvm" => {
+ mod zkvm;
+ pub use zkvm::*;
+ }
+ _ => {
+ mod unsupported;
+ pub use unsupported::*;
+ }
+}
diff --git a/crates/std/src/sys/env/unsupported.rs b/crates/std/src/sys/env/unsupported.rs
new file mode 100644
index 0000000..a967ace
--- /dev/null
+++ b/crates/std/src/sys/env/unsupported.rs
@@ -0,0 +1,33 @@
+use crate::ffi::{OsStr, OsString};
+use crate::{fmt, io};
+
+pub struct Env(!);
+
+impl fmt::Debug for Env {
+ fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.0
+ }
+}
+
+impl Iterator for Env {
+ type Item = (OsString, OsString);
+ fn next(&mut self) -> Option<(OsString, OsString)> {
+ self.0
+ }
+}
+
+pub fn env() -> Env {
+ panic!("not supported on this platform")
+}
+
+pub fn getenv(_: &OsStr) -> Option {
+ None
+}
+
+pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
+ Err(io::const_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
+}
+
+pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
+ Err(io::const_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
+}
diff --git a/crates/std/src/sys/mod.rs b/crates/std/src/sys/mod.rs
new file mode 100644
index 0000000..0b12d30
--- /dev/null
+++ b/crates/std/src/sys/mod.rs
@@ -0,0 +1,24 @@
+pub mod env;
+pub mod os_str;
+
+/// A trait for viewing representations from std types.
+#[cfg_attr(not(target_os = "linux"), allow(unused))]
+pub(crate) trait AsInner {
+ fn as_inner(&self) -> &Inner;
+}
+
+/// A trait for viewing representations from std types.
+#[cfg_attr(not(target_os = "linux"), allow(unused))]
+pub(crate) trait AsInnerMut {
+ fn as_inner_mut(&mut self) -> &mut Inner;
+}
+
+/// A trait for extracting representations from std types.
+pub(crate) trait IntoInner {
+ fn into_inner(self) -> Inner;
+}
+
+/// A trait for creating std types from internal representations.
+pub(crate) trait FromInner {
+ fn from_inner(inner: Inner) -> Self;
+}
diff --git a/crates/std/src/sys/os_str/bytes.rs b/crates/std/src/sys/os_str/bytes.rs
new file mode 100644
index 0000000..960d8c6
--- /dev/null
+++ b/crates/std/src/sys/os_str/bytes.rs
@@ -0,0 +1,363 @@
+//! The underlying OsString/OsStr implementation on Unix and many other
+//! systems: just a `Vec`/`[u8]`.
+
+use core::clone::CloneToUninit;
+
+use crate::borrow::Cow;
+use alloc::bstr::ByteStr;
+use alloc::collections::TryReserveError;
+use crate::rc::Rc;
+use alloc::sync::Arc;
+use crate::sys::{AsInner, FromInner, IntoInner};
+use crate::{fmt, mem, str};
+
+#[cfg(test)]
+mod tests;
+
+#[derive(Hash)]
+#[repr(transparent)]
+pub struct Buf {
+ pub inner: Vec,
+}
+
+#[repr(transparent)]
+pub struct Slice {
+ pub inner: [u8],
+}
+
+impl IntoInner> for Buf {
+ fn into_inner(self) -> Vec {
+ self.inner
+ }
+}
+
+impl FromInner> for Buf {
+ fn from_inner(inner: Vec) -> Self {
+ Buf { inner }
+ }
+}
+
+impl AsInner<[u8]> for Buf {
+ #[inline]
+ fn as_inner(&self) -> &[u8] {
+ &self.inner
+ }
+}
+
+impl fmt::Debug for Buf {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(self.as_slice(), f)
+ }
+}
+
+impl fmt::Display for Buf {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self.as_slice(), f)
+ }
+}
+
+impl fmt::Debug for Slice {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Debug::fmt(&self.inner.utf8_chunks().debug(), f)
+ }
+}
+
+impl fmt::Display for Slice {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(ByteStr::new(&self.inner), f)
+ }
+}
+
+impl Clone for Buf {
+ #[inline]
+ fn clone(&self) -> Self {
+ Buf { inner: self.inner.clone() }
+ }
+
+ #[inline]
+ fn clone_from(&mut self, source: &Self) {
+ self.inner.clone_from(&source.inner)
+ }
+}
+
+impl Buf {
+ #[inline]
+ pub fn into_encoded_bytes(self) -> Vec {
+ self.inner
+ }
+
+ #[inline]
+ pub unsafe fn from_encoded_bytes_unchecked(s: Vec) -> Self {
+ Self { inner: s }
+ }
+
+ #[inline]
+ pub fn into_string(self) -> Result {
+ String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() })
+ }
+
+ #[inline]
+ pub const fn from_string(s: String) -> Buf {
+ Buf { inner: s.into_bytes() }
+ }
+
+ #[inline]
+ pub fn with_capacity(capacity: usize) -> Buf {
+ Buf { inner: Vec::with_capacity(capacity) }
+ }
+
+ #[inline]
+ pub fn clear(&mut self) {
+ self.inner.clear()
+ }
+
+ #[inline]
+ pub fn capacity(&self) -> usize {
+ self.inner.capacity()
+ }
+
+ #[inline]
+ pub fn push_slice(&mut self, s: &Slice) {
+ self.inner.extend_from_slice(&s.inner)
+ }
+
+ #[inline]
+ pub fn push_str(&mut self, s: &str) {
+ self.inner.extend_from_slice(s.as_bytes());
+ }
+
+ #[inline]
+ pub fn reserve(&mut self, additional: usize) {
+ self.inner.reserve(additional)
+ }
+
+ #[inline]
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.inner.try_reserve(additional)
+ }
+
+ #[inline]
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.inner.reserve_exact(additional)
+ }
+
+ #[inline]
+ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ self.inner.try_reserve_exact(additional)
+ }
+
+ #[inline]
+ pub fn shrink_to_fit(&mut self) {
+ self.inner.shrink_to_fit()
+ }
+
+ #[inline]
+ pub fn shrink_to(&mut self, min_capacity: usize) {
+ self.inner.shrink_to(min_capacity)
+ }
+
+ #[inline]
+ pub fn as_slice(&self) -> &Slice {
+ // SAFETY: Slice is just a wrapper for [u8],
+ // and self.inner.as_slice() returns &[u8].
+ // Therefore, transmuting &[u8] to &Slice is safe.
+ unsafe { mem::transmute(self.inner.as_slice()) }
+ }
+
+ #[inline]
+ pub fn as_mut_slice(&mut self) -> &mut Slice {
+ // SAFETY: Slice is just a wrapper for [u8],
+ // and self.inner.as_mut_slice() returns &mut [u8].
+ // Therefore, transmuting &mut [u8] to &mut Slice is safe.
+ unsafe { mem::transmute(self.inner.as_mut_slice()) }
+ }
+
+ #[inline]
+ pub fn leak<'a>(self) -> &'a mut Slice {
+ unsafe { mem::transmute(self.inner.leak()) }
+ }
+
+ #[inline]
+ pub fn into_box(self) -> Box {
+ unsafe { mem::transmute(self.inner.into_boxed_slice()) }
+ }
+
+ #[inline]
+ pub fn from_box(boxed: Box) -> Buf {
+ let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
+ Buf { inner: inner.into_vec() }
+ }
+
+ #[inline]
+ pub fn into_arc(&self) -> Arc {
+ self.as_slice().into_arc()
+ }
+
+ #[inline]
+ pub fn into_rc(&self) -> Rc {
+ self.as_slice().into_rc()
+ }
+
+ /// Provides plumbing to `Vec::truncate` without giving full mutable access
+ /// to the `Vec`.
+ ///
+ /// # Safety
+ ///
+ /// The length must be at an `OsStr` boundary, according to
+ /// `Slice::check_public_boundary`.
+ #[inline]
+ pub unsafe fn truncate_unchecked(&mut self, len: usize) {
+ self.inner.truncate(len);
+ }
+
+ /// Provides plumbing to `Vec::extend_from_slice` without giving full
+ /// mutable access to the `Vec`.
+ ///
+ /// # Safety
+ ///
+ /// The slice must be valid for the platform encoding (as described in
+ /// `OsStr::from_encoded_bytes_unchecked`). This encoding has no safety
+ /// requirements.
+ #[inline]
+ pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
+ self.inner.extend_from_slice(other);
+ }
+}
+
+impl Slice {
+ #[inline]
+ pub fn as_encoded_bytes(&self) -> &[u8] {
+ &self.inner
+ }
+
+ #[inline]
+ pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
+ unsafe { mem::transmute(s) }
+ }
+
+ #[track_caller]
+ #[inline]
+ pub fn check_public_boundary(&self, index: usize) {
+ if index == 0 || index == self.inner.len() {
+ return;
+ }
+ if index < self.inner.len()
+ && (self.inner[index - 1].is_ascii() || self.inner[index].is_ascii())
+ {
+ return;
+ }
+
+ slow_path(&self.inner, index);
+
+ /// We're betting that typical splits will involve an ASCII character.
+ ///
+ /// Putting the expensive checks in a separate function generates notably
+ /// better assembly.
+ #[track_caller]
+ #[inline(never)]
+ fn slow_path(bytes: &[u8], index: usize) {
+ let (before, after) = bytes.split_at(index);
+
+ // UTF-8 takes at most 4 bytes per codepoint, so we don't
+ // need to check more than that.
+ let after = after.get(..4).unwrap_or(after);
+ match str::from_utf8(after) {
+ Ok(_) => return,
+ Err(err) if err.valid_up_to() != 0 => return,
+ Err(_) => (),
+ }
+
+ for len in 2..=4.min(index) {
+ let before = &before[index - len..];
+ if str::from_utf8(before).is_ok() {
+ return;
+ }
+ }
+
+ panic!("byte index {index} is not an OsStr boundary");
+ }
+ }
+
+ #[inline]
+ pub fn from_str(s: &str) -> &Slice {
+ unsafe { Slice::from_encoded_bytes_unchecked(s.as_bytes()) }
+ }
+
+ #[inline]
+ pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
+ str::from_utf8(&self.inner)
+ }
+
+ #[inline]
+ pub fn to_string_lossy(&self) -> Cow<'_, str> {
+ String::from_utf8_lossy(&self.inner)
+ }
+
+ #[inline]
+ pub fn to_owned(&self) -> Buf {
+ Buf { inner: self.inner.to_vec() }
+ }
+
+ #[inline]
+ pub fn clone_into(&self, buf: &mut Buf) {
+ self.inner.clone_into(&mut buf.inner)
+ }
+
+ #[inline]
+ pub fn empty_box() -> Box {
+ let boxed: Box<[u8]> = Default::default();
+ unsafe { mem::transmute(boxed) }
+ }
+
+ #[inline]
+ pub fn into_arc(&self) -> Arc {
+ let arc: Arc<[u8]> = Arc::from(&self.inner);
+ unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
+ }
+
+ #[inline]
+ pub fn into_rc(&self) -> Rc {
+ let rc: Rc<[u8]> = Rc::from(&self.inner);
+ unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
+ }
+
+ #[inline]
+ pub fn make_ascii_lowercase(&mut self) {
+ self.inner.make_ascii_lowercase()
+ }
+
+ #[inline]
+ pub fn make_ascii_uppercase(&mut self) {
+ self.inner.make_ascii_uppercase()
+ }
+
+ #[inline]
+ pub fn to_ascii_lowercase(&self) -> Buf {
+ Buf { inner: self.inner.to_ascii_lowercase() }
+ }
+
+ #[inline]
+ pub fn to_ascii_uppercase(&self) -> Buf {
+ Buf { inner: self.inner.to_ascii_uppercase() }
+ }
+
+ #[inline]
+ pub fn is_ascii(&self) -> bool {
+ self.inner.is_ascii()
+ }
+
+ #[inline]
+ pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
+ self.inner.eq_ignore_ascii_case(&other.inner)
+ }
+}
+
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for Slice {
+ #[inline]
+ #[cfg_attr(debug_assertions, track_caller)]
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ // SAFETY: we're just a transparent wrapper around [u8]
+ unsafe { self.inner.clone_to_uninit(dst) }
+ }
+}
diff --git a/crates/std/src/sys/os_str/bytes/tests.rs b/crates/std/src/sys/os_str/bytes/tests.rs
new file mode 100644
index 0000000..e2a9904
--- /dev/null
+++ b/crates/std/src/sys/os_str/bytes/tests.rs
@@ -0,0 +1,17 @@
+use super::*;
+
+#[test]
+fn slice_debug_output() {
+ let input = unsafe { Slice::from_encoded_bytes_unchecked(b"\xF0hello,\tworld") };
+ let expected = r#""\xF0hello,\tworld""#;
+ let output = format!("{input:?}");
+
+ assert_eq!(output, expected);
+}
+
+#[test]
+fn display() {
+ assert_eq!("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", unsafe {
+ Slice::from_encoded_bytes_unchecked(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string()
+ },);
+}
diff --git a/crates/std/src/sys/os_str/mod.rs b/crates/std/src/sys/os_str/mod.rs
new file mode 100644
index 0000000..f7007cb
--- /dev/null
+++ b/crates/std/src/sys/os_str/mod.rs
@@ -0,0 +1,16 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+
+cfg_select! {
+ any(target_os = "windows", target_os = "uefi") => {
+ mod wtf8;
+ pub use wtf8::{Buf, Slice};
+ }
+ any(target_os = "motor") => {
+ mod utf8;
+ pub use utf8::{Buf, Slice};
+ }
+ _ => {
+ mod bytes;
+ pub use bytes::{Buf, Slice};
+ }
+}
diff --git a/justfile b/justfile
index d8c779b..ba32dd5 100644
--- a/justfile
+++ b/justfile
@@ -17,13 +17,21 @@ cp_std path:
@echo "Copying {{ path }}"
@mkdir {{ "crates/std/src" / parent_directory(path) }} -p
@cp {{ rust_src / path }} {{ "crates/std/src" / path }}
- @perl -i -0777 -pe 's/^\s*#!?\[(un)?stable\(.*?\)\s*\]\n//gsm' {{ "crates/std/src" / path }}
- @perl -i -0777 -pe 's/^\s*#!?\[rustc_.*?\]\n//gsm' {{ "crates/std/src" / path }}
+ @sed -i -f patches.sed {{ "crates/std/src" / path }}
update_std:
+ @# Not copied : sys/mod.rs, io.rs
@just cp_std "ffi/c_str.rs"
@just cp_std "ffi/mod.rs"
@just cp_std "ffi/os_str.rs"
+ @just cp_std "ffi/os_str/tests.rs"
+ @just cp_std "sys/env/mod.rs"
+ @just cp_std "sys/env/unsupported.rs"
+ @just cp_std "sys/os_str/mod.rs"
+ @just cp_std "sys/os_str/bytes.rs"
+ @just cp_std "sys/os_str/bytes/tests.rs"
+ @# Copied but edited for the moment
+ # @just cp_std "hash/mod.rs"
build_user_prog prog:
RUSTFLAGS="-C relocation-model=pic -C link-arg=-Tuser.ld -C link-arg=-pie" cargo b {{ cargo_flags }} --package {{ prog }}
diff --git a/patches.sed b/patches.sed
new file mode 100644
index 0000000..921f281
--- /dev/null
+++ b/patches.sed
@@ -0,0 +1,6 @@
+s|crate::bstr::ByteStr|alloc::bstr::ByteStr|g
+s|crate::collections::TryReserveError|alloc::collections::TryReserveError|g
+s|crate::sync::Arc|alloc::sync::Arc|g
+
+# Ajouter d'autres modifications facilement ici :
+# s|ancien_texte|nouveau_texte|g
diff --git a/user/shell/src/main.rs b/user/shell/src/main.rs
index c531d7a..d8a5d7a 100644
--- a/user/shell/src/main.rs
+++ b/user/shell/src/main.rs
@@ -1,3 +1,5 @@
+#![feature(custom_std)]
+
fn main() -> isize {
println!(
"Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! "
diff --git a/user/test_pic/src/main.rs b/user/test_pic/src/main.rs
index a1c2f43..142a42e 100644
--- a/user/test_pic/src/main.rs
+++ b/user/test_pic/src/main.rs
@@ -1,3 +1,4 @@
+#![feature(custom_std)]
#![allow(unused)]
use std::{