std/ffi/os_str.rs
1//! The [`OsStr`] and [`OsString`] types and associated utilities.
2
3#[cfg(test)]
4mod tests;
5
6use core::clone::CloneToUninit;
7
8use crate::borrow::{Borrow, Cow};
9use crate::collections::TryReserveError;
10use crate::hash::{Hash, Hasher};
11use crate::ops::{self, Range};
12use crate::rc::Rc;
13use crate::str::FromStr;
14use crate::sync::Arc;
15use crate::sys::os_str::{Buf, Slice};
16use crate::sys::{AsInner, FromInner, IntoInner};
17use crate::{cmp, fmt, slice};
18
19/// A type that can represent owned, mutable platform-native strings, but is
20/// cheaply inter-convertible with Rust strings.
21///
22/// The need for this type arises from the fact that:
23///
24/// * On Unix systems, strings are often arbitrary sequences of non-zero
25/// bytes, in many cases interpreted as UTF-8.
26///
27/// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
28/// values, interpreted as UTF-16 when it is valid to do so.
29///
30/// * In Rust, strings are always valid UTF-8, which may contain zeros.
31///
32/// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
33/// and platform-native string values, and in particular allowing a Rust string
34/// to be converted into an "OS" string with no cost if possible. A consequence
35/// of this is that `OsString` instances are *not* `NUL` terminated; in order
36/// to pass to e.g., Unix system call, you should create a [`CStr`].
37///
38/// `OsString` is to <code>&[OsStr]</code> as [`String`] is to <code>&[str]</code>: the former
39/// in each pair are owned strings; the latter are borrowed
40/// references.
41///
42/// Note, `OsString` and [`OsStr`] internally do not necessarily hold strings in
43/// the form native to the platform; While on Unix, strings are stored as a
44/// sequence of 8-bit values, on Windows, where strings are 16-bit value based
45/// as just discussed, strings are also actually stored as a sequence of 8-bit
46/// values, encoded in a less-strict variant of UTF-8. This is useful to
47/// understand when handling capacity and length values.
48///
49/// # Capacity of `OsString`
50///
51/// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and
52/// uses units of bytes in an unspecified encoding for other contents. On a given target, all
53/// `OsString` and `OsStr` values use the same units for capacity, so the following will work:
54/// ```
55/// use std::ffi::{OsStr, OsString};
56///
57/// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
58/// let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
59/// ret.push(a); // This will not allocate further
60/// ret.push(b); // This will not allocate further
61/// ret
62/// }
63/// ```
64///
65/// # Creating an `OsString`
66///
67/// **From a Rust string**: `OsString` implements
68/// <code>[From]<[String]></code>, so you can use <code>my_string.[into]\()</code> to
69/// create an `OsString` from a normal Rust string.
70///
71/// **From slices:** Just like you can start with an empty Rust
72/// [`String`] and then [`String::push_str`] some <code>&[str]</code>
73/// sub-string slices into it, you can create an empty `OsString` with
74/// the [`OsString::new`] method and then push string slices into it with the
75/// [`OsString::push`] method.
76///
77/// # Extracting a borrowed reference to the whole OS string
78///
79/// You can use the [`OsString::as_os_str`] method to get an <code>&[OsStr]</code> from
80/// an `OsString`; this is effectively a borrowed reference to the
81/// whole string.
82///
83/// # Conversions
84///
85/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
86/// the traits which `OsString` implements for [conversions] from/to native representations.
87///
88/// [`CStr`]: crate::ffi::CStr
89/// [conversions]: super#conversions
90/// [into]: Into::into
91#[cfg_attr(not(test), rustc_diagnostic_item = "OsString")]
92#[stable(feature = "rust1", since = "1.0.0")]
93pub struct OsString {
94 inner: Buf,
95}
96
97/// Borrowed reference to an OS string (see [`OsString`]).
98///
99/// This type represents a borrowed reference to a string in the operating system's preferred
100/// representation.
101///
102/// `&OsStr` is to [`OsString`] as <code>&[str]</code> is to [`String`]: the
103/// former in each pair are borrowed references; the latter are owned strings.
104///
105/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
106/// the traits which `OsStr` implements for [conversions] from/to native representations.
107///
108/// [conversions]: super#conversions
109#[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
110#[stable(feature = "rust1", since = "1.0.0")]
111// `OsStr::from_inner` and `impl CloneToUninit for OsStr` current implementation relies
112// on `OsStr` being layout-compatible with `Slice`.
113// However, `OsStr` layout is considered an implementation detail and must not be relied upon.
114#[repr(transparent)]
115pub struct OsStr {
116 inner: Slice,
117}
118
119impl OsString {
120 /// Constructs a new empty `OsString`.
121 ///
122 /// # Examples
123 ///
124 /// ```
125 /// use std::ffi::OsString;
126 ///
127 /// let os_string = OsString::new();
128 /// ```
129 #[stable(feature = "rust1", since = "1.0.0")]
130 #[must_use]
131 #[inline]
132 #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "1.91.0")]
133 pub const fn new() -> OsString {
134 OsString { inner: Buf::from_string(String::new()) }
135 }
136
137 /// Converts bytes to an `OsString` without checking that the bytes contains
138 /// valid [`OsStr`]-encoded data.
139 ///
140 /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
141 /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
142 /// ASCII.
143 ///
144 /// See the [module's toplevel documentation about conversions][conversions] for safe,
145 /// cross-platform [conversions] from/to native representations.
146 ///
147 /// # Safety
148 ///
149 /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
150 /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
151 /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent
152 /// over the network or stored in a file will likely violate these safety rules.
153 ///
154 /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be
155 /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
156 ///
157 /// # Example
158 ///
159 /// ```
160 /// use std::ffi::OsStr;
161 ///
162 /// let os_str = OsStr::new("Mary had a little lamb");
163 /// let bytes = os_str.as_encoded_bytes();
164 /// let words = bytes.split(|b| *b == b' ');
165 /// let words: Vec<&OsStr> = words.map(|word| {
166 /// // SAFETY:
167 /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes`
168 /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
169 /// unsafe { OsStr::from_encoded_bytes_unchecked(word) }
170 /// }).collect();
171 /// ```
172 ///
173 /// [conversions]: super#conversions
174 #[inline]
175 #[stable(feature = "os_str_bytes", since = "1.74.0")]
176 pub unsafe fn from_encoded_bytes_unchecked(bytes: Vec<u8>) -> Self {
177 OsString { inner: unsafe { Buf::from_encoded_bytes_unchecked(bytes) } }
178 }
179
180 /// Converts to an [`OsStr`] slice.
181 ///
182 /// # Examples
183 ///
184 /// ```
185 /// use std::ffi::{OsString, OsStr};
186 ///
187 /// let os_string = OsString::from("foo");
188 /// let os_str = OsStr::new("foo");
189 /// assert_eq!(os_string.as_os_str(), os_str);
190 /// ```
191 #[cfg_attr(not(test), rustc_diagnostic_item = "os_string_as_os_str")]
192 #[stable(feature = "rust1", since = "1.0.0")]
193 #[must_use]
194 #[inline]
195 pub fn as_os_str(&self) -> &OsStr {
196 self
197 }
198
199 /// Converts the `OsString` into a byte vector. To convert the byte vector back into an
200 /// `OsString`, use the [`OsString::from_encoded_bytes_unchecked`] function.
201 ///
202 /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
203 /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
204 /// ASCII.
205 ///
206 /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
207 /// be treated as opaque and only comparable within the same Rust version built for the same
208 /// target platform. For example, sending the bytes over the network or storing it in a file
209 /// will likely result in incompatible data. See [`OsString`] for more encoding details
210 /// and [`std::ffi`] for platform-specific, specified conversions.
211 ///
212 /// [`std::ffi`]: crate::ffi
213 #[inline]
214 #[stable(feature = "os_str_bytes", since = "1.74.0")]
215 pub fn into_encoded_bytes(self) -> Vec<u8> {
216 self.inner.into_encoded_bytes()
217 }
218
219 /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
220 ///
221 /// On failure, ownership of the original `OsString` is returned.
222 ///
223 /// # Examples
224 ///
225 /// ```
226 /// use std::ffi::OsString;
227 ///
228 /// let os_string = OsString::from("foo");
229 /// let string = os_string.into_string();
230 /// assert_eq!(string, Ok(String::from("foo")));
231 /// ```
232 #[stable(feature = "rust1", since = "1.0.0")]
233 #[inline]
234 pub fn into_string(self) -> Result<String, OsString> {
235 self.inner.into_string().map_err(|buf| OsString { inner: buf })
236 }
237
238 /// Extends the string with the given <code>&[OsStr]</code> slice.
239 ///
240 /// # Examples
241 ///
242 /// ```
243 /// use std::ffi::OsString;
244 ///
245 /// let mut os_string = OsString::from("foo");
246 /// os_string.push("bar");
247 /// assert_eq!(&os_string, "foobar");
248 /// ```
249 #[stable(feature = "rust1", since = "1.0.0")]
250 #[inline]
251 #[rustc_confusables("append", "put")]
252 pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
253 trait SpecPushTo {
254 fn spec_push_to(&self, buf: &mut OsString);
255 }
256
257 impl<T: AsRef<OsStr>> SpecPushTo for T {
258 #[inline]
259 default fn spec_push_to(&self, buf: &mut OsString) {
260 buf.inner.push_slice(&self.as_ref().inner);
261 }
262 }
263
264 // Use a more efficient implementation when the string is UTF-8.
265 macro spec_str($T:ty) {
266 impl SpecPushTo for $T {
267 #[inline]
268 fn spec_push_to(&self, buf: &mut OsString) {
269 buf.inner.push_str(self);
270 }
271 }
272 }
273 spec_str!(str);
274 spec_str!(String);
275
276 s.spec_push_to(self)
277 }
278
279 /// Creates a new `OsString` with at least the given capacity.
280 ///
281 /// The string will be able to hold at least `capacity` length units of other
282 /// OS strings without reallocating. This method is allowed to allocate for
283 /// more units than `capacity`. If `capacity` is 0, the string will not
284 /// allocate.
285 ///
286 /// See the main `OsString` documentation information about encoding and capacity units.
287 ///
288 /// # Examples
289 ///
290 /// ```
291 /// use std::ffi::OsString;
292 ///
293 /// let mut os_string = OsString::with_capacity(10);
294 /// let capacity = os_string.capacity();
295 ///
296 /// // This push is done without reallocating
297 /// os_string.push("foo");
298 ///
299 /// assert_eq!(capacity, os_string.capacity());
300 /// ```
301 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
302 #[must_use]
303 #[inline]
304 pub fn with_capacity(capacity: usize) -> OsString {
305 OsString { inner: Buf::with_capacity(capacity) }
306 }
307
308 /// Truncates the `OsString` to zero length.
309 ///
310 /// # Examples
311 ///
312 /// ```
313 /// use std::ffi::OsString;
314 ///
315 /// let mut os_string = OsString::from("foo");
316 /// assert_eq!(&os_string, "foo");
317 ///
318 /// os_string.clear();
319 /// assert_eq!(&os_string, "");
320 /// ```
321 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
322 #[inline]
323 pub fn clear(&mut self) {
324 self.inner.clear()
325 }
326
327 /// Returns the capacity this `OsString` can hold without reallocating.
328 ///
329 /// See the main `OsString` documentation information about encoding and capacity units.
330 ///
331 /// # Examples
332 ///
333 /// ```
334 /// use std::ffi::OsString;
335 ///
336 /// let os_string = OsString::with_capacity(10);
337 /// assert!(os_string.capacity() >= 10);
338 /// ```
339 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
340 #[must_use]
341 #[inline]
342 pub fn capacity(&self) -> usize {
343 self.inner.capacity()
344 }
345
346 /// Reserves capacity for at least `additional` more capacity to be inserted
347 /// in the given `OsString`. Does nothing if the capacity is
348 /// already sufficient.
349 ///
350 /// The collection may reserve more space to speculatively avoid frequent reallocations.
351 ///
352 /// See the main `OsString` documentation information about encoding and capacity units.
353 ///
354 /// # Examples
355 ///
356 /// ```
357 /// use std::ffi::OsString;
358 ///
359 /// let mut s = OsString::new();
360 /// s.reserve(10);
361 /// assert!(s.capacity() >= 10);
362 /// ```
363 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
364 #[inline]
365 pub fn reserve(&mut self, additional: usize) {
366 self.inner.reserve(additional)
367 }
368
369 /// Tries to reserve capacity for at least `additional` more length units
370 /// in the given `OsString`. The string may reserve more space to speculatively avoid
371 /// frequent reallocations. After calling `try_reserve`, capacity will be
372 /// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
373 /// Does nothing if capacity is already sufficient. This method preserves
374 /// the contents even if an error occurs.
375 ///
376 /// See the main `OsString` documentation information about encoding and capacity units.
377 ///
378 /// # Errors
379 ///
380 /// If the capacity overflows, or the allocator reports a failure, then an error
381 /// is returned.
382 ///
383 /// # Examples
384 ///
385 /// ```
386 /// use std::ffi::{OsStr, OsString};
387 /// use std::collections::TryReserveError;
388 ///
389 /// fn process_data(data: &str) -> Result<OsString, TryReserveError> {
390 /// let mut s = OsString::new();
391 ///
392 /// // Pre-reserve the memory, exiting if we can't
393 /// s.try_reserve(OsStr::new(data).len())?;
394 ///
395 /// // Now we know this can't OOM in the middle of our complex work
396 /// s.push(data);
397 ///
398 /// Ok(s)
399 /// }
400 /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
401 /// ```
402 #[stable(feature = "try_reserve_2", since = "1.63.0")]
403 #[inline]
404 pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
405 self.inner.try_reserve(additional)
406 }
407
408 /// Reserves the minimum capacity for at least `additional` more capacity to
409 /// be inserted in the given `OsString`. Does nothing if the capacity is
410 /// already sufficient.
411 ///
412 /// Note that the allocator may give the collection more space than it
413 /// requests. Therefore, capacity can not be relied upon to be precisely
414 /// minimal. Prefer [`reserve`] if future insertions are expected.
415 ///
416 /// [`reserve`]: OsString::reserve
417 ///
418 /// See the main `OsString` documentation information about encoding and capacity units.
419 ///
420 /// # Examples
421 ///
422 /// ```
423 /// use std::ffi::OsString;
424 ///
425 /// let mut s = OsString::new();
426 /// s.reserve_exact(10);
427 /// assert!(s.capacity() >= 10);
428 /// ```
429 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
430 #[inline]
431 pub fn reserve_exact(&mut self, additional: usize) {
432 self.inner.reserve_exact(additional)
433 }
434
435 /// Tries to reserve the minimum capacity for at least `additional`
436 /// more length units in the given `OsString`. After calling
437 /// `try_reserve_exact`, capacity will be greater than or equal to
438 /// `self.len() + additional` if it returns `Ok(())`.
439 /// Does nothing if the capacity is already sufficient.
440 ///
441 /// Note that the allocator may give the `OsString` more space than it
442 /// requests. Therefore, capacity can not be relied upon to be precisely
443 /// minimal. Prefer [`try_reserve`] if future insertions are expected.
444 ///
445 /// [`try_reserve`]: OsString::try_reserve
446 ///
447 /// See the main `OsString` documentation information about encoding and capacity units.
448 ///
449 /// # Errors
450 ///
451 /// If the capacity overflows, or the allocator reports a failure, then an error
452 /// is returned.
453 ///
454 /// # Examples
455 ///
456 /// ```
457 /// use std::ffi::{OsStr, OsString};
458 /// use std::collections::TryReserveError;
459 ///
460 /// fn process_data(data: &str) -> Result<OsString, TryReserveError> {
461 /// let mut s = OsString::new();
462 ///
463 /// // Pre-reserve the memory, exiting if we can't
464 /// s.try_reserve_exact(OsStr::new(data).len())?;
465 ///
466 /// // Now we know this can't OOM in the middle of our complex work
467 /// s.push(data);
468 ///
469 /// Ok(s)
470 /// }
471 /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?");
472 /// ```
473 #[stable(feature = "try_reserve_2", since = "1.63.0")]
474 #[inline]
475 pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
476 self.inner.try_reserve_exact(additional)
477 }
478
479 /// Shrinks the capacity of the `OsString` to match its length.
480 ///
481 /// See the main `OsString` documentation information about encoding and capacity units.
482 ///
483 /// # Examples
484 ///
485 /// ```
486 /// use std::ffi::OsString;
487 ///
488 /// let mut s = OsString::from("foo");
489 ///
490 /// s.reserve(100);
491 /// assert!(s.capacity() >= 100);
492 ///
493 /// s.shrink_to_fit();
494 /// assert_eq!(3, s.capacity());
495 /// ```
496 #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
497 #[inline]
498 pub fn shrink_to_fit(&mut self) {
499 self.inner.shrink_to_fit()
500 }
501
502 /// Shrinks the capacity of the `OsString` with a lower bound.
503 ///
504 /// The capacity will remain at least as large as both the length
505 /// and the supplied value.
506 ///
507 /// If the current capacity is less than the lower limit, this is a no-op.
508 ///
509 /// See the main `OsString` documentation information about encoding and capacity units.
510 ///
511 /// # Examples
512 ///
513 /// ```
514 /// use std::ffi::OsString;
515 ///
516 /// let mut s = OsString::from("foo");
517 ///
518 /// s.reserve(100);
519 /// assert!(s.capacity() >= 100);
520 ///
521 /// s.shrink_to(10);
522 /// assert!(s.capacity() >= 10);
523 /// s.shrink_to(0);
524 /// assert!(s.capacity() >= 3);
525 /// ```
526 #[inline]
527 #[stable(feature = "shrink_to", since = "1.56.0")]
528 pub fn shrink_to(&mut self, min_capacity: usize) {
529 self.inner.shrink_to(min_capacity)
530 }
531
532 /// Converts this `OsString` into a boxed [`OsStr`].
533 ///
534 /// # Examples
535 ///
536 /// ```
537 /// use std::ffi::{OsString, OsStr};
538 ///
539 /// let s = OsString::from("hello");
540 ///
541 /// let b: Box<OsStr> = s.into_boxed_os_str();
542 /// ```
543 #[must_use = "`self` will be dropped if the result is not used"]
544 #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
545 pub fn into_boxed_os_str(self) -> Box<OsStr> {
546 let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
547 unsafe { Box::from_raw(rw) }
548 }
549
550 /// Consumes and leaks the `OsString`, returning a mutable reference to the contents,
551 /// `&'a mut OsStr`.
552 ///
553 /// The caller has free choice over the returned lifetime, including 'static.
554 /// Indeed, this function is ideally used for data that lives for the remainder of
555 /// the program’s life, as dropping the returned reference will cause a memory leak.
556 ///
557 /// It does not reallocate or shrink the `OsString`, so the leaked allocation may include
558 /// unused capacity that is not part of the returned slice. If you want to discard excess
559 /// capacity, call [`into_boxed_os_str`], and then [`Box::leak`] instead.
560 /// However, keep in mind that trimming the capacity may result in a reallocation and copy.
561 ///
562 /// [`into_boxed_os_str`]: Self::into_boxed_os_str
563 #[stable(feature = "os_string_pathbuf_leak", since = "1.89.0")]
564 #[inline]
565 pub fn leak<'a>(self) -> &'a mut OsStr {
566 OsStr::from_inner_mut(self.inner.leak())
567 }
568
569 /// Truncate the `OsString` to the specified length.
570 ///
571 /// If `new_len` is greater than the string's current length, this has no
572 /// effect.
573 ///
574 /// # Panics
575 ///
576 /// Panics if `len` does not lie on a valid `OsStr` boundary
577 /// (as described in [`OsStr::slice_encoded_bytes`]).
578 #[inline]
579 #[unstable(feature = "os_string_truncate", issue = "133262")]
580 pub fn truncate(&mut self, len: usize) {
581 if len <= self.len() {
582 self.as_os_str().inner.check_public_boundary(len);
583 // SAFETY: The length was just checked to be at a valid boundary.
584 unsafe { self.inner.truncate_unchecked(len) };
585 }
586 }
587
588 /// Provides plumbing to `Vec::extend_from_slice` without giving full
589 /// mutable access to the `Vec`.
590 ///
591 /// # Safety
592 ///
593 /// The slice must be valid for the platform encoding (as described in
594 /// [`OsStr::from_encoded_bytes_unchecked`]).
595 ///
596 /// This bypasses the encoding-dependent surrogate joining, so either
597 /// `self` must not end with a leading surrogate half, or `other` must not
598 /// start with a trailing surrogate half.
599 #[inline]
600 pub(crate) unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
601 // SAFETY: Guaranteed by caller.
602 unsafe { self.inner.extend_from_slice_unchecked(other) };
603 }
604}
605
606#[stable(feature = "rust1", since = "1.0.0")]
607impl From<String> for OsString {
608 /// Converts a [`String`] into an [`OsString`].
609 ///
610 /// This conversion does not allocate or copy memory.
611 #[inline]
612 fn from(s: String) -> OsString {
613 OsString { inner: Buf::from_string(s) }
614 }
615}
616
617#[stable(feature = "rust1", since = "1.0.0")]
618impl<T: ?Sized + AsRef<OsStr>> From<&T> for OsString {
619 /// Copies any value implementing <code>[AsRef]<[OsStr]></code>
620 /// into a newly allocated [`OsString`].
621 fn from(s: &T) -> OsString {
622 trait SpecToOsString {
623 fn spec_to_os_string(&self) -> OsString;
624 }
625
626 impl<T: AsRef<OsStr>> SpecToOsString for T {
627 #[inline]
628 default fn spec_to_os_string(&self) -> OsString {
629 self.as_ref().to_os_string()
630 }
631 }
632
633 // Preserve the known-UTF-8 property for strings.
634 macro spec_str($T:ty) {
635 impl SpecToOsString for $T {
636 #[inline]
637 fn spec_to_os_string(&self) -> OsString {
638 OsString::from(String::from(self))
639 }
640 }
641 }
642 spec_str!(str);
643 spec_str!(String);
644
645 s.spec_to_os_string()
646 }
647}
648
649#[stable(feature = "rust1", since = "1.0.0")]
650impl ops::Index<ops::RangeFull> for OsString {
651 type Output = OsStr;
652
653 #[inline]
654 fn index(&self, _index: ops::RangeFull) -> &OsStr {
655 OsStr::from_inner(self.inner.as_slice())
656 }
657}
658
659#[stable(feature = "mut_osstr", since = "1.44.0")]
660impl ops::IndexMut<ops::RangeFull> for OsString {
661 #[inline]
662 fn index_mut(&mut self, _index: ops::RangeFull) -> &mut OsStr {
663 OsStr::from_inner_mut(self.inner.as_mut_slice())
664 }
665}
666
667#[stable(feature = "rust1", since = "1.0.0")]
668impl ops::Deref for OsString {
669 type Target = OsStr;
670
671 #[inline]
672 fn deref(&self) -> &OsStr {
673 &self[..]
674 }
675}
676
677#[stable(feature = "mut_osstr", since = "1.44.0")]
678impl ops::DerefMut for OsString {
679 #[inline]
680 fn deref_mut(&mut self) -> &mut OsStr {
681 &mut self[..]
682 }
683}
684
685#[stable(feature = "osstring_default", since = "1.9.0")]
686impl Default for OsString {
687 /// Constructs an empty `OsString`.
688 #[inline]
689 fn default() -> OsString {
690 OsString::new()
691 }
692}
693
694#[stable(feature = "rust1", since = "1.0.0")]
695impl Clone for OsString {
696 #[inline]
697 fn clone(&self) -> Self {
698 OsString { inner: self.inner.clone() }
699 }
700
701 /// Clones the contents of `source` into `self`.
702 ///
703 /// This method is preferred over simply assigning `source.clone()` to `self`,
704 /// as it avoids reallocation if possible.
705 #[inline]
706 fn clone_from(&mut self, source: &Self) {
707 self.inner.clone_from(&source.inner)
708 }
709}
710
711#[stable(feature = "rust1", since = "1.0.0")]
712impl fmt::Debug for OsString {
713 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
714 fmt::Debug::fmt(&**self, formatter)
715 }
716}
717
718#[stable(feature = "rust1", since = "1.0.0")]
719impl PartialEq for OsString {
720 #[inline]
721 fn eq(&self, other: &OsString) -> bool {
722 &**self == &**other
723 }
724}
725
726#[stable(feature = "rust1", since = "1.0.0")]
727impl PartialEq<str> for OsString {
728 #[inline]
729 fn eq(&self, other: &str) -> bool {
730 &**self == other
731 }
732}
733
734#[stable(feature = "rust1", since = "1.0.0")]
735impl PartialEq<OsString> for str {
736 #[inline]
737 fn eq(&self, other: &OsString) -> bool {
738 &**other == self
739 }
740}
741
742#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
743impl PartialEq<&str> for OsString {
744 #[inline]
745 fn eq(&self, other: &&str) -> bool {
746 **self == **other
747 }
748}
749
750#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
751impl<'a> PartialEq<OsString> for &'a str {
752 #[inline]
753 fn eq(&self, other: &OsString) -> bool {
754 **other == **self
755 }
756}
757
758#[stable(feature = "rust1", since = "1.0.0")]
759impl Eq for OsString {}
760
761#[stable(feature = "rust1", since = "1.0.0")]
762impl PartialOrd for OsString {
763 #[inline]
764 fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
765 (&**self).partial_cmp(&**other)
766 }
767 #[inline]
768 fn lt(&self, other: &OsString) -> bool {
769 &**self < &**other
770 }
771 #[inline]
772 fn le(&self, other: &OsString) -> bool {
773 &**self <= &**other
774 }
775 #[inline]
776 fn gt(&self, other: &OsString) -> bool {
777 &**self > &**other
778 }
779 #[inline]
780 fn ge(&self, other: &OsString) -> bool {
781 &**self >= &**other
782 }
783}
784
785#[stable(feature = "rust1", since = "1.0.0")]
786impl PartialOrd<str> for OsString {
787 #[inline]
788 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
789 (&**self).partial_cmp(other)
790 }
791}
792
793#[stable(feature = "rust1", since = "1.0.0")]
794impl Ord for OsString {
795 #[inline]
796 fn cmp(&self, other: &OsString) -> cmp::Ordering {
797 (&**self).cmp(&**other)
798 }
799}
800
801#[stable(feature = "rust1", since = "1.0.0")]
802impl Hash for OsString {
803 #[inline]
804 fn hash<H: Hasher>(&self, state: &mut H) {
805 (&**self).hash(state)
806 }
807}
808
809#[stable(feature = "os_string_fmt_write", since = "1.64.0")]
810impl fmt::Write for OsString {
811 fn write_str(&mut self, s: &str) -> fmt::Result {
812 self.push(s);
813 Ok(())
814 }
815}
816
817impl OsStr {
818 /// Coerces into an `OsStr` slice.
819 ///
820 /// # Examples
821 ///
822 /// ```
823 /// use std::ffi::OsStr;
824 ///
825 /// let os_str = OsStr::new("foo");
826 /// ```
827 #[inline]
828 #[stable(feature = "rust1", since = "1.0.0")]
829 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
830 pub const fn new<S: [const] AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
831 s.as_ref()
832 }
833
834 /// Converts a slice of bytes to an OS string slice without checking that the string contains
835 /// valid `OsStr`-encoded data.
836 ///
837 /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
838 /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
839 /// ASCII.
840 ///
841 /// See the [module's toplevel documentation about conversions][conversions] for safe,
842 /// cross-platform [conversions] from/to native representations.
843 ///
844 /// # Safety
845 ///
846 /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
847 /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version
848 /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent
849 /// over the network or stored in a file will likely violate these safety rules.
850 ///
851 /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be
852 /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
853 ///
854 /// # Example
855 ///
856 /// ```
857 /// use std::ffi::OsStr;
858 ///
859 /// let os_str = OsStr::new("Mary had a little lamb");
860 /// let bytes = os_str.as_encoded_bytes();
861 /// let words = bytes.split(|b| *b == b' ');
862 /// let words: Vec<&OsStr> = words.map(|word| {
863 /// // SAFETY:
864 /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes`
865 /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
866 /// unsafe { OsStr::from_encoded_bytes_unchecked(word) }
867 /// }).collect();
868 /// ```
869 ///
870 /// [conversions]: super#conversions
871 #[inline]
872 #[stable(feature = "os_str_bytes", since = "1.74.0")]
873 pub unsafe fn from_encoded_bytes_unchecked(bytes: &[u8]) -> &Self {
874 Self::from_inner(unsafe { Slice::from_encoded_bytes_unchecked(bytes) })
875 }
876
877 #[inline]
878 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
879 const fn from_inner(inner: &Slice) -> &OsStr {
880 // SAFETY: OsStr is just a wrapper of Slice,
881 // therefore converting &Slice to &OsStr is safe.
882 unsafe { &*(inner as *const Slice as *const OsStr) }
883 }
884
885 #[inline]
886 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
887 const fn from_inner_mut(inner: &mut Slice) -> &mut OsStr {
888 // SAFETY: OsStr is just a wrapper of Slice,
889 // therefore converting &mut Slice to &mut OsStr is safe.
890 // Any method that mutates OsStr must be careful not to
891 // break platform-specific encoding, in particular Wtf8 on Windows.
892 unsafe { &mut *(inner as *mut Slice as *mut OsStr) }
893 }
894
895 /// Yields a <code>&[str]</code> slice if the `OsStr` is valid Unicode.
896 ///
897 /// This conversion may entail doing a check for UTF-8 validity.
898 ///
899 /// # Examples
900 ///
901 /// ```
902 /// use std::ffi::OsStr;
903 ///
904 /// let os_str = OsStr::new("foo");
905 /// assert_eq!(os_str.to_str(), Some("foo"));
906 /// ```
907 #[stable(feature = "rust1", since = "1.0.0")]
908 #[must_use = "this returns the result of the operation, \
909 without modifying the original"]
910 #[inline]
911 pub fn to_str(&self) -> Option<&str> {
912 self.inner.to_str().ok()
913 }
914
915 /// Converts an `OsStr` to a <code>[Cow]<[str]></code>.
916 ///
917 /// Any non-UTF-8 sequences are replaced with
918 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
919 ///
920 /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
921 ///
922 /// # Examples
923 ///
924 /// Calling `to_string_lossy` on an `OsStr` with invalid unicode:
925 ///
926 /// ```
927 /// // Note, due to differences in how Unix and Windows represent strings,
928 /// // we are forced to complicate this example, setting up example `OsStr`s
929 /// // with different source data and via different platform extensions.
930 /// // Understand that in reality you could end up with such example invalid
931 /// // sequences simply through collecting user command line arguments, for
932 /// // example.
933 ///
934 /// #[cfg(unix)] {
935 /// use std::ffi::OsStr;
936 /// use std::os::unix::ffi::OsStrExt;
937 ///
938 /// // Here, the values 0x66 and 0x6f correspond to 'f' and 'o'
939 /// // respectively. The value 0x80 is a lone continuation byte, invalid
940 /// // in a UTF-8 sequence.
941 /// let source = [0x66, 0x6f, 0x80, 0x6f];
942 /// let os_str = OsStr::from_bytes(&source[..]);
943 ///
944 /// assert_eq!(os_str.to_string_lossy(), "fo�o");
945 /// }
946 /// #[cfg(windows)] {
947 /// use std::ffi::OsString;
948 /// use std::os::windows::prelude::*;
949 ///
950 /// // Here the values 0x0066 and 0x006f correspond to 'f' and 'o'
951 /// // respectively. The value 0xD800 is a lone surrogate half, invalid
952 /// // in a UTF-16 sequence.
953 /// let source = [0x0066, 0x006f, 0xD800, 0x006f];
954 /// let os_string = OsString::from_wide(&source[..]);
955 /// let os_str = os_string.as_os_str();
956 ///
957 /// assert_eq!(os_str.to_string_lossy(), "fo�o");
958 /// }
959 /// ```
960 #[stable(feature = "rust1", since = "1.0.0")]
961 #[must_use = "this returns the result of the operation, \
962 without modifying the original"]
963 #[inline]
964 pub fn to_string_lossy(&self) -> Cow<'_, str> {
965 self.inner.to_string_lossy()
966 }
967
968 /// Copies the slice into an owned [`OsString`].
969 ///
970 /// # Examples
971 ///
972 /// ```
973 /// use std::ffi::{OsStr, OsString};
974 ///
975 /// let os_str = OsStr::new("foo");
976 /// let os_string = os_str.to_os_string();
977 /// assert_eq!(os_string, OsString::from("foo"));
978 /// ```
979 #[stable(feature = "rust1", since = "1.0.0")]
980 #[must_use = "this returns the result of the operation, \
981 without modifying the original"]
982 #[inline]
983 #[cfg_attr(not(test), rustc_diagnostic_item = "os_str_to_os_string")]
984 pub fn to_os_string(&self) -> OsString {
985 OsString { inner: self.inner.to_owned() }
986 }
987
988 /// Checks whether the `OsStr` is empty.
989 ///
990 /// # Examples
991 ///
992 /// ```
993 /// use std::ffi::OsStr;
994 ///
995 /// let os_str = OsStr::new("");
996 /// assert!(os_str.is_empty());
997 ///
998 /// let os_str = OsStr::new("foo");
999 /// assert!(!os_str.is_empty());
1000 /// ```
1001 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
1002 #[must_use]
1003 #[inline]
1004 pub fn is_empty(&self) -> bool {
1005 self.inner.inner.is_empty()
1006 }
1007
1008 /// Returns the length of this `OsStr`.
1009 ///
1010 /// Note that this does **not** return the number of bytes in the string in
1011 /// OS string form.
1012 ///
1013 /// The length returned is that of the underlying storage used by `OsStr`.
1014 /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr`
1015 /// store strings in a form best suited for cheap inter-conversion between
1016 /// native-platform and Rust string forms, which may differ significantly
1017 /// from both of them, including in storage size and encoding.
1018 ///
1019 /// This number is simply useful for passing to other methods, like
1020 /// [`OsString::with_capacity`] to avoid reallocations.
1021 ///
1022 /// See the main `OsString` documentation information about encoding and capacity units.
1023 ///
1024 /// # Examples
1025 ///
1026 /// ```
1027 /// use std::ffi::OsStr;
1028 ///
1029 /// let os_str = OsStr::new("");
1030 /// assert_eq!(os_str.len(), 0);
1031 ///
1032 /// let os_str = OsStr::new("foo");
1033 /// assert_eq!(os_str.len(), 3);
1034 /// ```
1035 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
1036 #[must_use]
1037 #[inline]
1038 pub fn len(&self) -> usize {
1039 self.inner.inner.len()
1040 }
1041
1042 /// Converts a <code>[Box]<[OsStr]></code> into an [`OsString`] without copying or allocating.
1043 #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
1044 #[must_use = "`self` will be dropped if the result is not used"]
1045 pub fn into_os_string(self: Box<Self>) -> OsString {
1046 let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
1047 OsString { inner: Buf::from_box(boxed) }
1048 }
1049
1050 /// Divides one string slice into two at an index.
1051 ///
1052 /// The two slices returned go from the start of the string slice to `mid`, and from `mid` to the end of the string slice.
1053 ///
1054 /// The argument, `mid`, should be a byte offset from the start of the string.
1055 /// It must also be on a valid `OsStr` boundary.
1056 /// See [`split_at_checked`][Self::split_at_checked] for the definition of a valid boundary.
1057 ///
1058 /// Panics
1059 ///
1060 /// Panics if `mid` is not on a valid boundary, or if it is past the end of the last code point of the string slice.
1061 /// For a non-panicking alternative see [`split_at_checked`][Self::split_at_checked].
1062 #[unstable(feature = "os_str_split_at", issue = "none")]
1063 pub fn split_at(&self, mid: usize) -> (&OsStr, &OsStr) {
1064 self.inner.check_public_boundary(mid);
1065
1066 // SAFETY: we've checked it's in bounds and a valid boundary
1067 unsafe { self.split_at_unchecked(mid) }
1068 }
1069
1070 /// Divides one string slice into two at an index.
1071 ///
1072 /// The two slices returned go from the start of the string slice to `mid`, and from `mid` to the end of the string slice.
1073 ///
1074 /// The argument, `mid`, should be a valid byte offset from the start of the string.
1075 /// It must also be on a valid `OsStr` boundary.
1076 /// The method returns `None` if that’s not the case.
1077 /// A valid `OsStr` boundary is one of:
1078 /// - The start of the string
1079 /// - The end of the string
1080 /// - The start of a valid non-empty UTF-8 substring
1081 /// - Immediately follows a valid non-empty UTF-8 substring
1082 #[unstable(feature = "os_str_split_at", issue = "none")]
1083 pub fn split_at_checked(&self, mid: usize) -> Option<(&OsStr, &OsStr)> {
1084 self.inner.try_check_public_boundary(mid)?;
1085
1086 // SAFETY: we've checked it's in bounds and a valid boundary
1087 unsafe { Some(self.split_at_unchecked(mid)) }
1088 }
1089
1090 /// Splits an `OsStr` without checking if `mid` is a valid boundary.
1091 /// You should use `split_at` or `split_at_checked` instead.
1092 ///
1093 /// # Safety
1094 ///
1095 /// Any caller must ensure `mid` is within bounds and lies on
1096 /// a valid `OsStr` boundary for the platform.
1097 unsafe fn split_at_unchecked(&self, mid: usize) -> (&OsStr, &OsStr) {
1098 // SAFETY: it's up to the caller to ensure this is safe.
1099 unsafe {
1100 let (first, second) = self.as_encoded_bytes().split_at_unchecked(mid);
1101 (Self::from_encoded_bytes_unchecked(first), Self::from_encoded_bytes_unchecked(second))
1102 }
1103 }
1104
1105 /// Converts an OS string slice to a byte slice. To convert the byte slice back into an OS
1106 /// string slice, use the [`OsStr::from_encoded_bytes_unchecked`] function.
1107 ///
1108 /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
1109 /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
1110 /// ASCII.
1111 ///
1112 /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
1113 /// be treated as opaque and only comparable within the same Rust version built for the same
1114 /// target platform. For example, sending the slice over the network or storing it in a file
1115 /// will likely result in incompatible byte slices. See [`OsString`] for more encoding details
1116 /// and [`std::ffi`] for platform-specific, specified conversions.
1117 ///
1118 /// [`std::ffi`]: crate::ffi
1119 #[inline]
1120 #[stable(feature = "os_str_bytes", since = "1.74.0")]
1121 pub fn as_encoded_bytes(&self) -> &[u8] {
1122 self.inner.as_encoded_bytes()
1123 }
1124
1125 /// Takes a substring based on a range that corresponds to the return value of
1126 /// [`OsStr::as_encoded_bytes`].
1127 ///
1128 /// The range's start and end must lie on valid `OsStr` boundaries.
1129 /// A valid `OsStr` boundary is one of:
1130 /// - The start of the string
1131 /// - The end of the string
1132 /// - Immediately before a valid non-empty UTF-8 substring
1133 /// - Immediately after a valid non-empty UTF-8 substring
1134 ///
1135 /// # Panics
1136 ///
1137 /// Panics if `range` does not lie on valid `OsStr` boundaries or if it
1138 /// exceeds the end of the string.
1139 ///
1140 /// # Example
1141 ///
1142 /// ```
1143 /// #![feature(os_str_slice)]
1144 ///
1145 /// use std::ffi::OsStr;
1146 ///
1147 /// let os_str = OsStr::new("foo=bar");
1148 /// let bytes = os_str.as_encoded_bytes();
1149 /// if let Some(index) = bytes.iter().position(|b| *b == b'=') {
1150 /// let key = os_str.slice_encoded_bytes(..index);
1151 /// let value = os_str.slice_encoded_bytes(index + 1..);
1152 /// assert_eq!(key, "foo");
1153 /// assert_eq!(value, "bar");
1154 /// }
1155 /// ```
1156 #[unstable(feature = "os_str_slice", issue = "118485")]
1157 pub fn slice_encoded_bytes<R: ops::RangeBounds<usize>>(&self, range: R) -> &Self {
1158 let encoded_bytes = self.as_encoded_bytes();
1159 let Range { start, end } = slice::range(range, ..encoded_bytes.len());
1160
1161 // `check_public_boundary` should panic if the index does not lie on an
1162 // `OsStr` boundary as described above. It's possible to do this in an
1163 // encoding-agnostic way, but details of the internal encoding might
1164 // permit a more efficient implementation.
1165 self.inner.check_public_boundary(start);
1166 self.inner.check_public_boundary(end);
1167
1168 // SAFETY: `slice::range` ensures that `start` and `end` are valid
1169 let slice = unsafe { encoded_bytes.get_unchecked(start..end) };
1170
1171 // SAFETY: `slice` comes from `self` and we validated the boundaries
1172 unsafe { Self::from_encoded_bytes_unchecked(slice) }
1173 }
1174
1175 /// Converts this string to its ASCII lower case equivalent in-place.
1176 ///
1177 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
1178 /// but non-ASCII letters are unchanged.
1179 ///
1180 /// To return a new lowercased value without modifying the existing one, use
1181 /// [`OsStr::to_ascii_lowercase`].
1182 ///
1183 /// # Examples
1184 ///
1185 /// ```
1186 /// use std::ffi::OsString;
1187 ///
1188 /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤");
1189 ///
1190 /// s.make_ascii_lowercase();
1191 ///
1192 /// assert_eq!("grÜße, jÜrgen ❤", s);
1193 /// ```
1194 #[stable(feature = "osstring_ascii", since = "1.53.0")]
1195 #[inline]
1196 pub fn make_ascii_lowercase(&mut self) {
1197 self.inner.make_ascii_lowercase()
1198 }
1199
1200 /// Converts this string to its ASCII upper case equivalent in-place.
1201 ///
1202 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
1203 /// but non-ASCII letters are unchanged.
1204 ///
1205 /// To return a new uppercased value without modifying the existing one, use
1206 /// [`OsStr::to_ascii_uppercase`].
1207 ///
1208 /// # Examples
1209 ///
1210 /// ```
1211 /// use std::ffi::OsString;
1212 ///
1213 /// let mut s = OsString::from("Grüße, Jürgen ❤");
1214 ///
1215 /// s.make_ascii_uppercase();
1216 ///
1217 /// assert_eq!("GRüßE, JüRGEN ❤", s);
1218 /// ```
1219 #[stable(feature = "osstring_ascii", since = "1.53.0")]
1220 #[inline]
1221 pub fn make_ascii_uppercase(&mut self) {
1222 self.inner.make_ascii_uppercase()
1223 }
1224
1225 /// Returns a copy of this string where each character is mapped to its
1226 /// ASCII lower case equivalent.
1227 ///
1228 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
1229 /// but non-ASCII letters are unchanged.
1230 ///
1231 /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`].
1232 ///
1233 /// # Examples
1234 ///
1235 /// ```
1236 /// use std::ffi::OsString;
1237 /// let s = OsString::from("Grüße, Jürgen ❤");
1238 ///
1239 /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
1240 /// ```
1241 #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase`"]
1242 #[stable(feature = "osstring_ascii", since = "1.53.0")]
1243 pub fn to_ascii_lowercase(&self) -> OsString {
1244 OsString::from_inner(self.inner.to_ascii_lowercase())
1245 }
1246
1247 /// Returns a copy of this string where each character is mapped to its
1248 /// ASCII upper case equivalent.
1249 ///
1250 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
1251 /// but non-ASCII letters are unchanged.
1252 ///
1253 /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`].
1254 ///
1255 /// # Examples
1256 ///
1257 /// ```
1258 /// use std::ffi::OsString;
1259 /// let s = OsString::from("Grüße, Jürgen ❤");
1260 ///
1261 /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
1262 /// ```
1263 #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase`"]
1264 #[stable(feature = "osstring_ascii", since = "1.53.0")]
1265 pub fn to_ascii_uppercase(&self) -> OsString {
1266 OsString::from_inner(self.inner.to_ascii_uppercase())
1267 }
1268
1269 /// Checks if all characters in this string are within the ASCII range.
1270 ///
1271 /// An empty string returns `true`.
1272 ///
1273 /// # Examples
1274 ///
1275 /// ```
1276 /// use std::ffi::OsString;
1277 ///
1278 /// let ascii = OsString::from("hello!\n");
1279 /// let non_ascii = OsString::from("Grüße, Jürgen ❤");
1280 ///
1281 /// assert!(ascii.is_ascii());
1282 /// assert!(!non_ascii.is_ascii());
1283 /// ```
1284 #[stable(feature = "osstring_ascii", since = "1.53.0")]
1285 #[must_use]
1286 #[inline]
1287 pub fn is_ascii(&self) -> bool {
1288 self.inner.is_ascii()
1289 }
1290
1291 /// Checks that two strings are an ASCII case-insensitive match.
1292 ///
1293 /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
1294 /// but without allocating and copying temporaries.
1295 ///
1296 /// # Examples
1297 ///
1298 /// ```
1299 /// use std::ffi::OsString;
1300 ///
1301 /// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS"));
1302 /// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS"));
1303 /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS"));
1304 /// ```
1305 #[stable(feature = "osstring_ascii", since = "1.53.0")]
1306 pub fn eq_ignore_ascii_case<S: AsRef<OsStr>>(&self, other: S) -> bool {
1307 self.inner.eq_ignore_ascii_case(&other.as_ref().inner)
1308 }
1309
1310 /// Returns an object that implements [`Display`] for safely printing an
1311 /// [`OsStr`] that may contain non-Unicode data. This may perform lossy
1312 /// conversion, depending on the platform. If you would like an
1313 /// implementation which escapes the [`OsStr`] please use [`Debug`]
1314 /// instead.
1315 ///
1316 /// [`Display`]: fmt::Display
1317 /// [`Debug`]: fmt::Debug
1318 ///
1319 /// # Examples
1320 ///
1321 /// ```
1322 /// use std::ffi::OsStr;
1323 ///
1324 /// let s = OsStr::new("Hello, world!");
1325 /// println!("{}", s.display());
1326 /// ```
1327 #[stable(feature = "os_str_display", since = "1.87.0")]
1328 #[must_use = "this does not display the `OsStr`; \
1329 it returns an object that can be displayed"]
1330 #[inline]
1331 pub fn display(&self) -> Display<'_> {
1332 Display { os_str: self }
1333 }
1334
1335 /// Returns the same string as a string slice `&OsStr`.
1336 ///
1337 /// This method is redundant when used directly on `&OsStr`, but
1338 /// it helps dereferencing other string-like types to string slices,
1339 /// for example references to `Box<OsStr>` or `Arc<OsStr>`.
1340 #[inline]
1341 #[unstable(feature = "str_as_str", issue = "130366")]
1342 pub const fn as_os_str(&self) -> &OsStr {
1343 self
1344 }
1345}
1346
1347#[stable(feature = "box_from_os_str", since = "1.17.0")]
1348impl From<&OsStr> for Box<OsStr> {
1349 /// Copies the string into a newly allocated <code>[Box]<[OsStr]></code>.
1350 #[inline]
1351 fn from(s: &OsStr) -> Box<OsStr> {
1352 Box::clone_from_ref(s)
1353 }
1354}
1355
1356#[stable(feature = "box_from_mut_slice", since = "1.84.0")]
1357impl From<&mut OsStr> for Box<OsStr> {
1358 /// Copies the string into a newly allocated <code>[Box]<[OsStr]></code>.
1359 #[inline]
1360 fn from(s: &mut OsStr) -> Box<OsStr> {
1361 Self::from(&*s)
1362 }
1363}
1364
1365#[stable(feature = "box_from_cow", since = "1.45.0")]
1366impl From<Cow<'_, OsStr>> for Box<OsStr> {
1367 /// Converts a `Cow<'a, OsStr>` into a <code>[Box]<[OsStr]></code>,
1368 /// by copying the contents if they are borrowed.
1369 #[inline]
1370 fn from(cow: Cow<'_, OsStr>) -> Box<OsStr> {
1371 match cow {
1372 Cow::Borrowed(s) => Box::from(s),
1373 Cow::Owned(s) => Box::from(s),
1374 }
1375 }
1376}
1377
1378#[stable(feature = "os_string_from_box", since = "1.18.0")]
1379impl From<Box<OsStr>> for OsString {
1380 /// Converts a <code>[Box]<[OsStr]></code> into an [`OsString`] without copying or
1381 /// allocating.
1382 #[inline]
1383 fn from(boxed: Box<OsStr>) -> OsString {
1384 boxed.into_os_string()
1385 }
1386}
1387
1388#[stable(feature = "box_from_os_string", since = "1.20.0")]
1389impl From<OsString> for Box<OsStr> {
1390 /// Converts an [`OsString`] into a <code>[Box]<[OsStr]></code> without copying or allocating.
1391 #[inline]
1392 fn from(s: OsString) -> Box<OsStr> {
1393 s.into_boxed_os_str()
1394 }
1395}
1396
1397#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
1398impl Clone for Box<OsStr> {
1399 #[inline]
1400 fn clone(&self) -> Self {
1401 self.to_os_string().into_boxed_os_str()
1402 }
1403}
1404
1405#[unstable(feature = "clone_to_uninit", issue = "126799")]
1406unsafe impl CloneToUninit for OsStr {
1407 #[inline]
1408 #[cfg_attr(debug_assertions, track_caller)]
1409 unsafe fn clone_to_uninit(&self, dst: *mut u8) {
1410 // SAFETY: we're just a transparent wrapper around a platform-specific Slice
1411 unsafe { self.inner.clone_to_uninit(dst) }
1412 }
1413}
1414
1415#[stable(feature = "shared_from_slice2", since = "1.24.0")]
1416impl From<OsString> for Arc<OsStr> {
1417 /// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> by moving the [`OsString`]
1418 /// data into a new [`Arc`] buffer.
1419 #[inline]
1420 fn from(s: OsString) -> Arc<OsStr> {
1421 let arc = s.inner.into_arc();
1422 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
1423 }
1424}
1425
1426#[stable(feature = "shared_from_slice2", since = "1.24.0")]
1427impl From<&OsStr> for Arc<OsStr> {
1428 /// Copies the string into a newly allocated <code>[Arc]<[OsStr]></code>.
1429 #[inline]
1430 fn from(s: &OsStr) -> Arc<OsStr> {
1431 let arc = s.inner.into_arc();
1432 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
1433 }
1434}
1435
1436#[stable(feature = "shared_from_mut_slice", since = "1.84.0")]
1437impl From<&mut OsStr> for Arc<OsStr> {
1438 /// Copies the string into a newly allocated <code>[Arc]<[OsStr]></code>.
1439 #[inline]
1440 fn from(s: &mut OsStr) -> Arc<OsStr> {
1441 Arc::from(&*s)
1442 }
1443}
1444
1445#[stable(feature = "shared_from_slice2", since = "1.24.0")]
1446impl From<OsString> for Rc<OsStr> {
1447 /// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> by moving the [`OsString`]
1448 /// data into a new [`Rc`] buffer.
1449 #[inline]
1450 fn from(s: OsString) -> Rc<OsStr> {
1451 let rc = s.inner.into_rc();
1452 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
1453 }
1454}
1455
1456#[stable(feature = "shared_from_slice2", since = "1.24.0")]
1457impl From<&OsStr> for Rc<OsStr> {
1458 /// Copies the string into a newly allocated <code>[Rc]<[OsStr]></code>.
1459 #[inline]
1460 fn from(s: &OsStr) -> Rc<OsStr> {
1461 let rc = s.inner.into_rc();
1462 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
1463 }
1464}
1465
1466#[stable(feature = "shared_from_mut_slice", since = "1.84.0")]
1467impl From<&mut OsStr> for Rc<OsStr> {
1468 /// Copies the string into a newly allocated <code>[Rc]<[OsStr]></code>.
1469 #[inline]
1470 fn from(s: &mut OsStr) -> Rc<OsStr> {
1471 Rc::from(&*s)
1472 }
1473}
1474
1475#[stable(feature = "cow_from_osstr", since = "1.28.0")]
1476impl<'a> From<OsString> for Cow<'a, OsStr> {
1477 /// Moves the string into a [`Cow::Owned`].
1478 #[inline]
1479 fn from(s: OsString) -> Cow<'a, OsStr> {
1480 Cow::Owned(s)
1481 }
1482}
1483
1484#[stable(feature = "cow_from_osstr", since = "1.28.0")]
1485impl<'a> From<&'a OsStr> for Cow<'a, OsStr> {
1486 /// Converts the string reference into a [`Cow::Borrowed`].
1487 #[inline]
1488 fn from(s: &'a OsStr) -> Cow<'a, OsStr> {
1489 Cow::Borrowed(s)
1490 }
1491}
1492
1493#[stable(feature = "cow_from_osstr", since = "1.28.0")]
1494impl<'a> From<&'a OsString> for Cow<'a, OsStr> {
1495 /// Converts the string reference into a [`Cow::Borrowed`].
1496 #[inline]
1497 fn from(s: &'a OsString) -> Cow<'a, OsStr> {
1498 Cow::Borrowed(s.as_os_str())
1499 }
1500}
1501
1502#[stable(feature = "osstring_from_cow_osstr", since = "1.28.0")]
1503impl<'a> From<Cow<'a, OsStr>> for OsString {
1504 /// Converts a `Cow<'a, OsStr>` into an [`OsString`],
1505 /// by copying the contents if they are borrowed.
1506 #[inline]
1507 fn from(s: Cow<'a, OsStr>) -> Self {
1508 s.into_owned()
1509 }
1510}
1511
1512#[stable(feature = "str_tryfrom_osstr_impl", since = "1.72.0")]
1513impl<'a> TryFrom<&'a OsStr> for &'a str {
1514 type Error = crate::str::Utf8Error;
1515
1516 /// Tries to convert an `&OsStr` to a `&str`.
1517 ///
1518 /// ```
1519 /// use std::ffi::OsStr;
1520 ///
1521 /// let os_str = OsStr::new("foo");
1522 /// let as_str = <&str>::try_from(os_str).unwrap();
1523 /// assert_eq!(as_str, "foo");
1524 /// ```
1525 fn try_from(value: &'a OsStr) -> Result<Self, Self::Error> {
1526 value.inner.to_str()
1527 }
1528}
1529
1530#[stable(feature = "box_default_extra", since = "1.17.0")]
1531impl Default for Box<OsStr> {
1532 #[inline]
1533 fn default() -> Box<OsStr> {
1534 let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
1535 unsafe { Box::from_raw(rw) }
1536 }
1537}
1538
1539#[stable(feature = "osstring_default", since = "1.9.0")]
1540impl Default for &OsStr {
1541 /// Creates an empty `OsStr`.
1542 #[inline]
1543 fn default() -> Self {
1544 OsStr::new("")
1545 }
1546}
1547
1548#[stable(feature = "rust1", since = "1.0.0")]
1549impl PartialEq for OsStr {
1550 #[inline]
1551 fn eq(&self, other: &OsStr) -> bool {
1552 self.as_encoded_bytes().eq(other.as_encoded_bytes())
1553 }
1554}
1555
1556#[stable(feature = "rust1", since = "1.0.0")]
1557impl PartialEq<str> for OsStr {
1558 #[inline]
1559 fn eq(&self, other: &str) -> bool {
1560 *self == *OsStr::new(other)
1561 }
1562}
1563
1564#[stable(feature = "rust1", since = "1.0.0")]
1565impl PartialEq<OsStr> for str {
1566 #[inline]
1567 fn eq(&self, other: &OsStr) -> bool {
1568 *other == *OsStr::new(self)
1569 }
1570}
1571
1572#[stable(feature = "rust1", since = "1.0.0")]
1573impl Eq for OsStr {}
1574
1575#[stable(feature = "rust1", since = "1.0.0")]
1576impl PartialOrd for OsStr {
1577 #[inline]
1578 fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
1579 self.as_encoded_bytes().partial_cmp(other.as_encoded_bytes())
1580 }
1581 #[inline]
1582 fn lt(&self, other: &OsStr) -> bool {
1583 self.as_encoded_bytes().lt(other.as_encoded_bytes())
1584 }
1585 #[inline]
1586 fn le(&self, other: &OsStr) -> bool {
1587 self.as_encoded_bytes().le(other.as_encoded_bytes())
1588 }
1589 #[inline]
1590 fn gt(&self, other: &OsStr) -> bool {
1591 self.as_encoded_bytes().gt(other.as_encoded_bytes())
1592 }
1593 #[inline]
1594 fn ge(&self, other: &OsStr) -> bool {
1595 self.as_encoded_bytes().ge(other.as_encoded_bytes())
1596 }
1597}
1598
1599#[stable(feature = "rust1", since = "1.0.0")]
1600impl PartialOrd<str> for OsStr {
1601 #[inline]
1602 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
1603 self.partial_cmp(OsStr::new(other))
1604 }
1605}
1606
1607// FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
1608// have more flexible coherence rules.
1609
1610#[stable(feature = "rust1", since = "1.0.0")]
1611impl Ord for OsStr {
1612 #[inline]
1613 fn cmp(&self, other: &OsStr) -> cmp::Ordering {
1614 self.as_encoded_bytes().cmp(other.as_encoded_bytes())
1615 }
1616}
1617
1618macro_rules! impl_cmp {
1619 ($lhs:ty, $rhs: ty) => {
1620 #[stable(feature = "cmp_os_str", since = "1.8.0")]
1621 impl PartialEq<$rhs> for $lhs {
1622 #[inline]
1623 fn eq(&self, other: &$rhs) -> bool {
1624 <OsStr as PartialEq>::eq(self, other)
1625 }
1626 }
1627
1628 #[stable(feature = "cmp_os_str", since = "1.8.0")]
1629 impl PartialEq<$lhs> for $rhs {
1630 #[inline]
1631 fn eq(&self, other: &$lhs) -> bool {
1632 <OsStr as PartialEq>::eq(self, other)
1633 }
1634 }
1635
1636 #[stable(feature = "cmp_os_str", since = "1.8.0")]
1637 impl PartialOrd<$rhs> for $lhs {
1638 #[inline]
1639 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
1640 <OsStr as PartialOrd>::partial_cmp(self, other)
1641 }
1642 }
1643
1644 #[stable(feature = "cmp_os_str", since = "1.8.0")]
1645 impl PartialOrd<$lhs> for $rhs {
1646 #[inline]
1647 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
1648 <OsStr as PartialOrd>::partial_cmp(self, other)
1649 }
1650 }
1651 };
1652}
1653
1654impl_cmp!(OsString, OsStr);
1655impl_cmp!(OsString, &OsStr);
1656impl_cmp!(Cow<'_, OsStr>, OsStr);
1657impl_cmp!(Cow<'_, OsStr>, &OsStr);
1658impl_cmp!(Cow<'_, OsStr>, OsString);
1659
1660#[stable(feature = "rust1", since = "1.0.0")]
1661impl Hash for OsStr {
1662 #[inline]
1663 fn hash<H: Hasher>(&self, state: &mut H) {
1664 self.as_encoded_bytes().hash(state)
1665 }
1666}
1667
1668#[stable(feature = "rust1", since = "1.0.0")]
1669impl fmt::Debug for OsStr {
1670 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1671 fmt::Debug::fmt(&self.inner, formatter)
1672 }
1673}
1674
1675/// Helper struct for safely printing an [`OsStr`] with [`format!`] and `{}`.
1676///
1677/// An [`OsStr`] might contain non-Unicode data. This `struct` implements the
1678/// [`Display`] trait in a way that mitigates that. It is created by the
1679/// [`display`](OsStr::display) method on [`OsStr`]. This may perform lossy
1680/// conversion, depending on the platform. If you would like an implementation
1681/// which escapes the [`OsStr`] please use [`Debug`] instead.
1682///
1683/// # Examples
1684///
1685/// ```
1686/// use std::ffi::OsStr;
1687///
1688/// let s = OsStr::new("Hello, world!");
1689/// println!("{}", s.display());
1690/// ```
1691///
1692/// [`Display`]: fmt::Display
1693/// [`format!`]: crate::format
1694#[stable(feature = "os_str_display", since = "1.87.0")]
1695pub struct Display<'a> {
1696 os_str: &'a OsStr,
1697}
1698
1699#[stable(feature = "os_str_display", since = "1.87.0")]
1700impl fmt::Debug for Display<'_> {
1701 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1702 fmt::Debug::fmt(&self.os_str, f)
1703 }
1704}
1705
1706#[stable(feature = "os_str_display", since = "1.87.0")]
1707impl fmt::Display for Display<'_> {
1708 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1709 fmt::Display::fmt(&self.os_str.inner, f)
1710 }
1711}
1712
1713#[unstable(feature = "slice_concat_ext", issue = "27747")]
1714impl<S: Borrow<OsStr>> alloc::slice::Join<&OsStr> for [S] {
1715 type Output = OsString;
1716
1717 fn join(slice: &Self, sep: &OsStr) -> OsString {
1718 let Some((first, suffix)) = slice.split_first() else {
1719 return OsString::new();
1720 };
1721 let first_owned = first.borrow().to_owned();
1722 suffix.iter().fold(first_owned, |mut a, b| {
1723 a.push(sep);
1724 a.push(b.borrow());
1725 a
1726 })
1727 }
1728}
1729
1730#[stable(feature = "rust1", since = "1.0.0")]
1731impl Borrow<OsStr> for OsString {
1732 #[inline]
1733 fn borrow(&self) -> &OsStr {
1734 &self[..]
1735 }
1736}
1737
1738#[stable(feature = "rust1", since = "1.0.0")]
1739impl ToOwned for OsStr {
1740 type Owned = OsString;
1741 #[inline]
1742 fn to_owned(&self) -> OsString {
1743 self.to_os_string()
1744 }
1745 #[inline]
1746 fn clone_into(&self, target: &mut OsString) {
1747 self.inner.clone_into(&mut target.inner)
1748 }
1749}
1750
1751#[stable(feature = "rust1", since = "1.0.0")]
1752#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1753const impl AsRef<OsStr> for OsStr {
1754 #[inline]
1755 fn as_ref(&self) -> &OsStr {
1756 self
1757 }
1758}
1759
1760#[stable(feature = "rust1", since = "1.0.0")]
1761impl AsRef<OsStr> for OsString {
1762 #[inline]
1763 fn as_ref(&self) -> &OsStr {
1764 self
1765 }
1766}
1767
1768#[stable(feature = "rust1", since = "1.0.0")]
1769impl AsRef<OsStr> for str {
1770 #[inline]
1771 fn as_ref(&self) -> &OsStr {
1772 OsStr::from_inner(Slice::from_str(self))
1773 }
1774}
1775
1776#[stable(feature = "rust1", since = "1.0.0")]
1777impl AsRef<OsStr> for String {
1778 #[inline]
1779 fn as_ref(&self) -> &OsStr {
1780 (&**self).as_ref()
1781 }
1782}
1783
1784impl FromInner<Buf> for OsString {
1785 #[inline]
1786 fn from_inner(buf: Buf) -> OsString {
1787 OsString { inner: buf }
1788 }
1789}
1790
1791impl IntoInner<Buf> for OsString {
1792 #[inline]
1793 fn into_inner(self) -> Buf {
1794 self.inner
1795 }
1796}
1797
1798impl AsInner<Slice> for OsStr {
1799 #[inline]
1800 fn as_inner(&self) -> &Slice {
1801 &self.inner
1802 }
1803}
1804
1805#[stable(feature = "osstring_from_str", since = "1.45.0")]
1806impl FromStr for OsString {
1807 type Err = core::convert::Infallible;
1808
1809 #[inline]
1810 fn from_str(s: &str) -> Result<Self, Self::Err> {
1811 Ok(OsString::from(s))
1812 }
1813}
1814
1815#[stable(feature = "osstring_extend", since = "1.52.0")]
1816impl Extend<OsString> for OsString {
1817 #[inline]
1818 fn extend<T: IntoIterator<Item = OsString>>(&mut self, iter: T) {
1819 for s in iter {
1820 self.push(&s);
1821 }
1822 }
1823}
1824
1825#[stable(feature = "osstring_extend", since = "1.52.0")]
1826impl<'a> Extend<&'a OsStr> for OsString {
1827 #[inline]
1828 fn extend<T: IntoIterator<Item = &'a OsStr>>(&mut self, iter: T) {
1829 for s in iter {
1830 self.push(s);
1831 }
1832 }
1833}
1834
1835#[stable(feature = "osstring_extend", since = "1.52.0")]
1836impl<'a> Extend<Cow<'a, OsStr>> for OsString {
1837 #[inline]
1838 fn extend<T: IntoIterator<Item = Cow<'a, OsStr>>>(&mut self, iter: T) {
1839 for s in iter {
1840 self.push(&s);
1841 }
1842 }
1843}
1844
1845#[stable(feature = "osstring_extend", since = "1.52.0")]
1846impl FromIterator<OsString> for OsString {
1847 #[inline]
1848 fn from_iter<I: IntoIterator<Item = OsString>>(iter: I) -> Self {
1849 let mut iterator = iter.into_iter();
1850
1851 // Because we're iterating over `OsString`s, we can avoid at least
1852 // one allocation by getting the first string from the iterator
1853 // and appending to it all the subsequent strings.
1854 match iterator.next() {
1855 None => OsString::new(),
1856 Some(mut buf) => {
1857 buf.extend(iterator);
1858 buf
1859 }
1860 }
1861 }
1862}
1863
1864#[stable(feature = "osstring_extend", since = "1.52.0")]
1865impl<'a> FromIterator<&'a OsStr> for OsString {
1866 #[inline]
1867 fn from_iter<I: IntoIterator<Item = &'a OsStr>>(iter: I) -> Self {
1868 let mut buf = Self::new();
1869 for s in iter {
1870 buf.push(s);
1871 }
1872 buf
1873 }
1874}
1875
1876#[stable(feature = "osstring_extend", since = "1.52.0")]
1877impl<'a> FromIterator<Cow<'a, OsStr>> for OsString {
1878 #[inline]
1879 fn from_iter<I: IntoIterator<Item = Cow<'a, OsStr>>>(iter: I) -> Self {
1880 let mut iterator = iter.into_iter();
1881
1882 // Because we're iterating over `OsString`s, we can avoid at least
1883 // one allocation by getting the first owned string from the iterator
1884 // and appending to it all the subsequent strings.
1885 match iterator.next() {
1886 None => OsString::new(),
1887 Some(Cow::Owned(mut buf)) => {
1888 buf.extend(iterator);
1889 buf
1890 }
1891 Some(Cow::Borrowed(buf)) => {
1892 let mut buf = OsString::from(buf);
1893 buf.extend(iterator);
1894 buf
1895 }
1896 }
1897 }
1898}