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