]> git.proxmox.com Git - rustc.git/blame - library/std/src/ffi/os_str.rs
New upstream version 1.50.0+dfsg1
[rustc.git] / library / std / src / ffi / os_str.rs
CommitLineData
1b1a35ee
XL
1#[cfg(test)]
2mod tests;
3
532ac7d7 4use crate::borrow::{Borrow, Cow};
532ac7d7 5use crate::cmp;
dfeec247 6use crate::fmt;
532ac7d7 7use crate::hash::{Hash, Hasher};
dfeec247 8use crate::ops;
532ac7d7 9use crate::rc::Rc;
f9f354fc 10use crate::str::FromStr;
532ac7d7 11use crate::sync::Arc;
85aaf69f 12
532ac7d7 13use crate::sys::os_str::{Buf, Slice};
dfeec247 14use crate::sys_common::{AsInner, FromInner, IntoInner};
85aaf69f 15
9cc50fc6 16/// A type that can represent owned, mutable platform-native strings, but is
54a0048b 17/// cheaply inter-convertible with Rust strings.
9cc50fc6
SL
18///
19/// The need for this type arises from the fact that:
20///
21/// * On Unix systems, strings are often arbitrary sequences of non-zero
22/// bytes, in many cases interpreted as UTF-8.
23///
24/// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
25/// values, interpreted as UTF-16 when it is valid to do so.
26///
041b39d2 27/// * In Rust, strings are always valid UTF-8, which may contain zeros.
9cc50fc6 28///
32a655c1 29/// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
9cc50fc6 30/// and platform-native string values, and in particular allowing a Rust string
9fa01778 31/// to be converted into an "OS" string with no cost if possible. A consequence
0bf4aa26 32/// of this is that `OsString` instances are *not* `NUL` terminated; in order
0731742a 33/// to pass to e.g., Unix system call, you should create a [`CStr`].
abe05a73 34///
2c00a5a8 35/// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former
abe05a73
XL
36/// in each pair are owned strings; the latter are borrowed
37/// references.
38///
416331ca 39/// Note, `OsString` and [`OsStr`] internally do not necessarily hold strings in
a1dfa0c6
XL
40/// the form native to the platform; While on Unix, strings are stored as a
41/// sequence of 8-bit values, on Windows, where strings are 16-bit value based
42/// as just discussed, strings are also actually stored as a sequence of 8-bit
43/// values, encoded in a less-strict variant of UTF-8. This is useful to
44/// understand when handling capacity and length values.
45///
abe05a73
XL
46/// # Creating an `OsString`
47///
48/// **From a Rust string**: `OsString` implements
49/// [`From`]`<`[`String`]`>`, so you can use `my_string.from` to
50/// create an `OsString` from a normal Rust string.
51///
52/// **From slices:** Just like you can start with an empty Rust
3dfed10e 53/// [`String`] and then [`String::push_str`] `&str`
abe05a73 54/// sub-string slices into it, you can create an empty `OsString` with
3dfed10e
XL
55/// the [`OsString::new`] method and then push string slices into it with the
56/// [`OsString::push`] method.
abe05a73
XL
57///
58/// # Extracting a borrowed reference to the whole OS string
59///
3dfed10e 60/// You can use the [`OsString::as_os_str`] method to get an `&`[`OsStr`] from
abe05a73
XL
61/// an `OsString`; this is effectively a borrowed reference to the
62/// whole string.
63///
64/// # Conversions
65///
66/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
83c7162d 67/// the traits which `OsString` implements for [conversions] from/to native representations.
32a655c1 68///
3dfed10e
XL
69/// [`&OsStr`]: OsStr
70/// [`&str`]: str
71/// [`CStr`]: crate::ffi::CStr
29967ef6 72/// [conversions]: super#conversions
85aaf69f 73#[derive(Clone)]
c34b1796 74#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 75pub struct OsString {
dfeec247 76 inner: Buf,
85aaf69f
SL
77}
78
abe05a73
XL
79/// Borrowed reference to an OS string (see [`OsString`]).
80///
81/// This type represents a borrowed reference to a string in the operating system's preferred
82/// representation.
83///
2c00a5a8 84/// `&OsStr` is to [`OsString`] as [`&str`] is to [`String`]: the former in each pair are borrowed
abe05a73
XL
85/// references; the latter are owned strings.
86///
87/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
83c7162d 88/// the traits which `OsStr` implements for [conversions] from/to native representations.
32a655c1 89///
3dfed10e 90/// [`&str`]: str
29967ef6 91/// [conversions]: super#conversions
c34b1796 92#[stable(feature = "rust1", since = "1.0.0")]
416331ca
XL
93// FIXME:
94// `OsStr::from_inner` current implementation relies
95// on `OsStr` being layout-compatible with `Slice`.
96// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
1b1a35ee 97// Anyway, `OsStr` representation and layout are considered implementation details, are
416331ca 98// not documented and must not be relied upon.
85aaf69f 99pub struct OsStr {
dfeec247 100 inner: Slice,
85aaf69f
SL
101}
102
103impl OsString {
85aaf69f 104 /// Constructs a new empty `OsString`.
32a655c1
SL
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// use std::ffi::OsString;
110 ///
111 /// let os_string = OsString::new();
112 /// ```
c34b1796 113 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
114 pub fn new() -> OsString {
115 OsString { inner: Buf::from_string(String::new()) }
116 }
117
32a655c1
SL
118 /// Converts to an [`OsStr`] slice.
119 ///
32a655c1
SL
120 /// # Examples
121 ///
122 /// ```
123 /// use std::ffi::{OsString, OsStr};
124 ///
125 /// let os_string = OsString::from("foo");
126 /// let os_str = OsStr::new("foo");
127 /// assert_eq!(os_string.as_os_str(), os_str);
128 /// ```
c34b1796
AL
129 #[stable(feature = "rust1", since = "1.0.0")]
130 pub fn as_os_str(&self) -> &OsStr {
131 self
132 }
133
32a655c1 134 /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
85aaf69f
SL
135 ///
136 /// On failure, ownership of the original `OsString` is returned.
32a655c1 137 ///
32a655c1
SL
138 /// # Examples
139 ///
140 /// ```
141 /// use std::ffi::OsString;
142 ///
143 /// let os_string = OsString::from("foo");
144 /// let string = os_string.into_string();
145 /// assert_eq!(string, Ok(String::from("foo")));
146 /// ```
c34b1796 147 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 148 pub fn into_string(self) -> Result<String, OsString> {
dfeec247 149 self.inner.into_string().map_err(|buf| OsString { inner: buf })
85aaf69f
SL
150 }
151
32a655c1
SL
152 /// Extends the string with the given [`&OsStr`] slice.
153 ///
3dfed10e 154 /// [`&OsStr`]: OsStr
32a655c1
SL
155 ///
156 /// # Examples
157 ///
158 /// ```
159 /// use std::ffi::OsString;
160 ///
161 /// let mut os_string = OsString::from("foo");
162 /// os_string.push("bar");
163 /// assert_eq!(&os_string, "foobar");
164 /// ```
c34b1796
AL
165 #[stable(feature = "rust1", since = "1.0.0")]
166 pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
167 self.inner.push_slice(&s.as_ref().inner)
168 }
7453a54e 169
54a0048b
SL
170 /// Creates a new `OsString` with the given capacity.
171 ///
3b2f2976 172 /// The string will be able to hold exactly `capacity` length units of other
54a0048b
SL
173 /// OS strings without reallocating. If `capacity` is 0, the string will not
174 /// allocate.
7453a54e
SL
175 ///
176 /// See main `OsString` documentation information about encoding.
32a655c1
SL
177 ///
178 /// # Examples
179 ///
180 /// ```
181 /// use std::ffi::OsString;
182 ///
183 /// let mut os_string = OsString::with_capacity(10);
184 /// let capacity = os_string.capacity();
185 ///
186 /// // This push is done without reallocating
187 /// os_string.push("foo");
188 ///
189 /// assert_eq!(capacity, os_string.capacity());
190 /// ```
54a0048b 191 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e 192 pub fn with_capacity(capacity: usize) -> OsString {
dfeec247 193 OsString { inner: Buf::with_capacity(capacity) }
7453a54e
SL
194 }
195
196 /// Truncates the `OsString` to zero length.
32a655c1
SL
197 ///
198 /// # Examples
199 ///
200 /// ```
201 /// use std::ffi::OsString;
202 ///
203 /// let mut os_string = OsString::from("foo");
204 /// assert_eq!(&os_string, "foo");
205 ///
206 /// os_string.clear();
207 /// assert_eq!(&os_string, "");
208 /// ```
54a0048b 209 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
210 pub fn clear(&mut self) {
211 self.inner.clear()
212 }
213
54a0048b 214 /// Returns the capacity this `OsString` can hold without reallocating.
7453a54e
SL
215 ///
216 /// See `OsString` introduction for information about encoding.
32a655c1
SL
217 ///
218 /// # Examples
219 ///
220 /// ```
221 /// use std::ffi::OsString;
222 ///
e1599b0c 223 /// let os_string = OsString::with_capacity(10);
32a655c1
SL
224 /// assert!(os_string.capacity() >= 10);
225 /// ```
54a0048b 226 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
227 pub fn capacity(&self) -> usize {
228 self.inner.capacity()
229 }
230
54a0048b
SL
231 /// Reserves capacity for at least `additional` more capacity to be inserted
232 /// in the given `OsString`.
233 ///
234 /// The collection may reserve more space to avoid frequent reallocations.
cc61c64b
XL
235 ///
236 /// # Examples
237 ///
238 /// ```
239 /// use std::ffi::OsString;
240 ///
241 /// let mut s = OsString::new();
242 /// s.reserve(10);
243 /// assert!(s.capacity() >= 10);
244 /// ```
54a0048b 245 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
246 pub fn reserve(&mut self, additional: usize) {
247 self.inner.reserve(additional)
248 }
249
54a0048b
SL
250 /// Reserves the minimum capacity for exactly `additional` more capacity to
251 /// be inserted in the given `OsString`. Does nothing if the capacity is
7453a54e
SL
252 /// already sufficient.
253 ///
254 /// Note that the allocator may give the collection more space than it
9fa01778 255 /// requests. Therefore, capacity can not be relied upon to be precisely
7453a54e 256 /// minimal. Prefer reserve if future insertions are expected.
cc61c64b
XL
257 ///
258 /// # Examples
259 ///
260 /// ```
261 /// use std::ffi::OsString;
262 ///
263 /// let mut s = OsString::new();
264 /// s.reserve_exact(10);
265 /// assert!(s.capacity() >= 10);
266 /// ```
54a0048b 267 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
268 pub fn reserve_exact(&mut self, additional: usize) {
269 self.inner.reserve_exact(additional)
270 }
8bb4bdeb
XL
271
272 /// Shrinks the capacity of the `OsString` to match its length.
cc61c64b
XL
273 ///
274 /// # Examples
275 ///
276 /// ```
cc61c64b
XL
277 /// use std::ffi::OsString;
278 ///
279 /// let mut s = OsString::from("foo");
280 ///
281 /// s.reserve(100);
282 /// assert!(s.capacity() >= 100);
283 ///
284 /// s.shrink_to_fit();
285 /// assert_eq!(3, s.capacity());
286 /// ```
7cac9316 287 #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
8bb4bdeb
XL
288 pub fn shrink_to_fit(&mut self) {
289 self.inner.shrink_to_fit()
290 }
291
0531ce1d
XL
292 /// Shrinks the capacity of the `OsString` with a lower bound.
293 ///
294 /// The capacity will remain at least as large as both the length
295 /// and the supplied value.
296 ///
297 /// Panics if the current capacity is smaller than the supplied
298 /// minimum capacity.
299 ///
300 /// # Examples
301 ///
302 /// ```
303 /// #![feature(shrink_to)]
304 /// use std::ffi::OsString;
305 ///
306 /// let mut s = OsString::from("foo");
307 ///
308 /// s.reserve(100);
309 /// assert!(s.capacity() >= 100);
310 ///
311 /// s.shrink_to(10);
312 /// assert!(s.capacity() >= 10);
313 /// s.shrink_to(0);
314 /// assert!(s.capacity() >= 3);
315 /// ```
316 #[inline]
dfeec247 317 #[unstable(feature = "shrink_to", reason = "new API", issue = "56431")]
0531ce1d
XL
318 pub fn shrink_to(&mut self, min_capacity: usize) {
319 self.inner.shrink_to(min_capacity)
320 }
321
7cac9316
XL
322 /// Converts this `OsString` into a boxed [`OsStr`].
323 ///
cc61c64b
XL
324 /// # Examples
325 ///
326 /// ```
cc61c64b
XL
327 /// use std::ffi::{OsString, OsStr};
328 ///
329 /// let s = OsString::from("hello");
330 ///
331 /// let b: Box<OsStr> = s.into_boxed_os_str();
332 /// ```
041b39d2 333 #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
8bb4bdeb 334 pub fn into_boxed_os_str(self) -> Box<OsStr> {
ea8adc8c
XL
335 let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
336 unsafe { Box::from_raw(rw) }
8bb4bdeb 337 }
c34b1796
AL
338}
339
340#[stable(feature = "rust1", since = "1.0.0")]
341impl From<String> for OsString {
b7449926
XL
342 /// Converts a [`String`] into a [`OsString`].
343 ///
344 /// The conversion copies the data, and includes an allocation on the heap.
c34b1796
AL
345 fn from(s: String) -> OsString {
346 OsString { inner: Buf::from_string(s) }
347 }
348}
349
350#[stable(feature = "rust1", since = "1.0.0")]
532ac7d7
XL
351impl<T: ?Sized + AsRef<OsStr>> From<&T> for OsString {
352 fn from(s: &T) -> OsString {
c34b1796 353 s.as_ref().to_os_string()
85aaf69f
SL
354 }
355}
356
c34b1796 357#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
358impl ops::Index<ops::RangeFull> for OsString {
359 type Output = OsStr;
360
361 #[inline]
c34b1796 362 fn index(&self, _index: ops::RangeFull) -> &OsStr {
e9174d1e 363 OsStr::from_inner(self.inner.as_slice())
85aaf69f
SL
364 }
365}
366
ba9703b0
XL
367#[stable(feature = "mut_osstr", since = "1.44.0")]
368impl ops::IndexMut<ops::RangeFull> for OsString {
369 #[inline]
370 fn index_mut(&mut self, _index: ops::RangeFull) -> &mut OsStr {
371 OsStr::from_inner_mut(self.inner.as_mut_slice())
372 }
373}
374
c34b1796 375#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
376impl ops::Deref for OsString {
377 type Target = OsStr;
378
379 #[inline]
380 fn deref(&self) -> &OsStr {
381 &self[..]
382 }
383}
384
ba9703b0
XL
385#[stable(feature = "mut_osstr", since = "1.44.0")]
386impl ops::DerefMut for OsString {
387 #[inline]
388 fn deref_mut(&mut self) -> &mut OsStr {
389 &mut self[..]
390 }
391}
392
54a0048b
SL
393#[stable(feature = "osstring_default", since = "1.9.0")]
394impl Default for OsString {
9e0c209e 395 /// Constructs an empty `OsString`.
54a0048b
SL
396 #[inline]
397 fn default() -> OsString {
398 OsString::new()
399 }
400}
401
c34b1796 402#[stable(feature = "rust1", since = "1.0.0")]
041b39d2 403impl fmt::Debug for OsString {
532ac7d7 404 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
85aaf69f
SL
405 fmt::Debug::fmt(&**self, formatter)
406 }
407}
408
c34b1796 409#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
410impl PartialEq for OsString {
411 fn eq(&self, other: &OsString) -> bool {
412 &**self == &**other
413 }
414}
415
c34b1796 416#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
417impl PartialEq<str> for OsString {
418 fn eq(&self, other: &str) -> bool {
419 &**self == other
420 }
421}
422
c34b1796 423#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
424impl PartialEq<OsString> for str {
425 fn eq(&self, other: &OsString) -> bool {
426 &**other == self
427 }
428}
429
b7449926 430#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
532ac7d7
XL
431impl PartialEq<&str> for OsString {
432 fn eq(&self, other: &&str) -> bool {
8faf50e0
XL
433 **self == **other
434 }
435}
436
b7449926 437#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
8faf50e0
XL
438impl<'a> PartialEq<OsString> for &'a str {
439 fn eq(&self, other: &OsString) -> bool {
440 **other == **self
441 }
442}
443
c34b1796 444#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
445impl Eq for OsString {}
446
c34b1796 447#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
448impl PartialOrd for OsString {
449 #[inline]
450 fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
451 (&**self).partial_cmp(&**other)
452 }
453 #[inline]
dfeec247
XL
454 fn lt(&self, other: &OsString) -> bool {
455 &**self < &**other
456 }
85aaf69f 457 #[inline]
dfeec247
XL
458 fn le(&self, other: &OsString) -> bool {
459 &**self <= &**other
460 }
85aaf69f 461 #[inline]
dfeec247
XL
462 fn gt(&self, other: &OsString) -> bool {
463 &**self > &**other
464 }
85aaf69f 465 #[inline]
dfeec247
XL
466 fn ge(&self, other: &OsString) -> bool {
467 &**self >= &**other
468 }
85aaf69f
SL
469}
470
c34b1796 471#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
472impl PartialOrd<str> for OsString {
473 #[inline]
474 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
475 (&**self).partial_cmp(other)
476 }
477}
478
c34b1796 479#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
480impl Ord for OsString {
481 #[inline]
482 fn cmp(&self, other: &OsString) -> cmp::Ordering {
483 (&**self).cmp(&**other)
484 }
485}
486
85aaf69f
SL
487#[stable(feature = "rust1", since = "1.0.0")]
488impl Hash for OsString {
489 #[inline]
490 fn hash<H: Hasher>(&self, state: &mut H) {
491 (&**self).hash(state)
492 }
493}
494
495impl OsStr {
9346a6ac 496 /// Coerces into an `OsStr` slice.
9e0c209e
SL
497 ///
498 /// # Examples
499 ///
500 /// ```
501 /// use std::ffi::OsStr;
502 ///
503 /// let os_str = OsStr::new("foo");
504 /// ```
60c5eb7d 505 #[inline]
c34b1796
AL
506 #[stable(feature = "rust1", since = "1.0.0")]
507 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
508 s.as_ref()
509 }
510
60c5eb7d 511 #[inline]
e9174d1e 512 fn from_inner(inner: &Slice) -> &OsStr {
1b1a35ee 513 // SAFETY: OsStr is just a wrapper of Slice,
ba9703b0 514 // therefore converting &Slice to &OsStr is safe.
ea8adc8c 515 unsafe { &*(inner as *const Slice as *const OsStr) }
e9174d1e
SL
516 }
517
ba9703b0
XL
518 #[inline]
519 fn from_inner_mut(inner: &mut Slice) -> &mut OsStr {
1b1a35ee 520 // SAFETY: OsStr is just a wrapper of Slice,
ba9703b0
XL
521 // therefore converting &mut Slice to &mut OsStr is safe.
522 // Any method that mutates OsStr must be careful not to
523 // break platform-specific encoding, in particular Wtf8 on Windows.
524 unsafe { &mut *(inner as *mut Slice as *mut OsStr) }
525 }
526
32a655c1 527 /// Yields a [`&str`] slice if the `OsStr` is valid Unicode.
85aaf69f
SL
528 ///
529 /// This conversion may entail doing a check for UTF-8 validity.
32a655c1 530 ///
3dfed10e 531 /// [`&str`]: str
32a655c1
SL
532 ///
533 /// # Examples
534 ///
535 /// ```
536 /// use std::ffi::OsStr;
537 ///
538 /// let os_str = OsStr::new("foo");
539 /// assert_eq!(os_str.to_str(), Some("foo"));
540 /// ```
c34b1796 541 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
542 pub fn to_str(&self) -> Option<&str> {
543 self.inner.to_str()
544 }
545
32a655c1 546 /// Converts an `OsStr` to a [`Cow`]`<`[`str`]`>`.
85aaf69f 547 ///
b7449926
XL
548 /// Any non-Unicode sequences are replaced with
549 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
32a655c1 550 ///
3dfed10e 551 /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
32a655c1
SL
552 ///
553 /// # Examples
554 ///
0731742a 555 /// Calling `to_string_lossy` on an `OsStr` with invalid unicode:
32a655c1
SL
556 ///
557 /// ```
0731742a
XL
558 /// // Note, due to differences in how Unix and Windows represent strings,
559 /// // we are forced to complicate this example, setting up example `OsStr`s
560 /// // with different source data and via different platform extensions.
561 /// // Understand that in reality you could end up with such example invalid
562 /// // sequences simply through collecting user command line arguments, for
563 /// // example.
32a655c1 564 ///
0731742a
XL
565 /// #[cfg(any(unix, target_os = "redox"))] {
566 /// use std::ffi::OsStr;
567 /// use std::os::unix::ffi::OsStrExt;
32a655c1 568 ///
0731742a
XL
569 /// // Here, the values 0x66 and 0x6f correspond to 'f' and 'o'
570 /// // respectively. The value 0x80 is a lone continuation byte, invalid
571 /// // in a UTF-8 sequence.
572 /// let source = [0x66, 0x6f, 0x80, 0x6f];
573 /// let os_str = OsStr::from_bytes(&source[..]);
574 ///
575 /// assert_eq!(os_str.to_string_lossy(), "fo�o");
576 /// }
577 /// #[cfg(windows)] {
578 /// use std::ffi::OsString;
579 /// use std::os::windows::prelude::*;
580 ///
581 /// // Here the values 0x0066 and 0x006f correspond to 'f' and 'o'
582 /// // respectively. The value 0xD800 is a lone surrogate half, invalid
583 /// // in a UTF-16 sequence.
584 /// let source = [0x0066, 0x006f, 0xD800, 0x006f];
585 /// let os_string = OsString::from_wide(&source[..]);
586 /// let os_str = os_string.as_os_str();
587 ///
588 /// assert_eq!(os_str.to_string_lossy(), "fo�o");
589 /// }
590 /// ```
c34b1796 591 #[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 592 pub fn to_string_lossy(&self) -> Cow<'_, str> {
85aaf69f
SL
593 self.inner.to_string_lossy()
594 }
595
32a655c1
SL
596 /// Copies the slice into an owned [`OsString`].
597 ///
cc61c64b
XL
598 /// # Examples
599 ///
600 /// ```
601 /// use std::ffi::{OsStr, OsString};
602 ///
603 /// let os_str = OsStr::new("foo");
604 /// let os_string = os_str.to_os_string();
605 /// assert_eq!(os_string, OsString::from("foo"));
606 /// ```
c34b1796 607 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
608 pub fn to_os_string(&self) -> OsString {
609 OsString { inner: self.inner.to_owned() }
610 }
611
7453a54e 612 /// Checks whether the `OsStr` is empty.
9e0c209e
SL
613 ///
614 /// # Examples
615 ///
616 /// ```
617 /// use std::ffi::OsStr;
618 ///
619 /// let os_str = OsStr::new("");
620 /// assert!(os_str.is_empty());
621 ///
622 /// let os_str = OsStr::new("foo");
623 /// assert!(!os_str.is_empty());
624 /// ```
54a0048b 625 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
dfeec247 626 #[inline]
7453a54e
SL
627 pub fn is_empty(&self) -> bool {
628 self.inner.inner.is_empty()
629 }
630
54a0048b
SL
631 /// Returns the length of this `OsStr`.
632 ///
a1dfa0c6
XL
633 /// Note that this does **not** return the number of bytes in the string in
634 /// OS string form.
635 ///
e1599b0c 636 /// The length returned is that of the underlying storage used by `OsStr`.
a1dfa0c6
XL
637 /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr`
638 /// store strings in a form best suited for cheap inter-conversion between
639 /// native-platform and Rust string forms, which may differ significantly
640 /// from both of them, including in storage size and encoding.
7453a54e 641 ///
a1dfa0c6
XL
642 /// This number is simply useful for passing to other methods, like
643 /// [`OsString::with_capacity`] to avoid reallocations.
9e0c209e
SL
644 ///
645 /// # Examples
646 ///
647 /// ```
648 /// use std::ffi::OsStr;
649 ///
650 /// let os_str = OsStr::new("");
651 /// assert_eq!(os_str.len(), 0);
652 ///
653 /// let os_str = OsStr::new("foo");
654 /// assert_eq!(os_str.len(), 3);
655 /// ```
54a0048b 656 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
657 pub fn len(&self) -> usize {
658 self.inner.inner.len()
659 }
660
7cac9316 661 /// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating.
041b39d2 662 #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
cc61c64b 663 pub fn into_os_string(self: Box<OsStr>) -> OsString {
ea8adc8c
XL
664 let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
665 OsString { inner: Buf::from_box(boxed) }
cc61c64b
XL
666 }
667
9346a6ac 668 /// Gets the underlying byte representation.
85aaf69f 669 ///
fc512014 670 /// Note: it is *crucial* that this API is not externally public, to avoid
85aaf69f 671 /// revealing the internal, platform-specific encodings.
60c5eb7d 672 #[inline]
fc512014 673 pub(crate) fn bytes(&self) -> &[u8] {
ea8adc8c 674 unsafe { &*(&self.inner as *const _ as *const [u8]) }
85aaf69f 675 }
ba9703b0
XL
676
677 /// Converts this string to its ASCII lower case equivalent in-place.
678 ///
679 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
680 /// but non-ASCII letters are unchanged.
681 ///
682 /// To return a new lowercased value without modifying the existing one, use
3dfed10e 683 /// [`OsStr::to_ascii_lowercase`].
ba9703b0
XL
684 ///
685 /// # Examples
686 ///
687 /// ```
688 /// #![feature(osstring_ascii)]
689 /// use std::ffi::OsString;
690 ///
691 /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤");
692 ///
693 /// s.make_ascii_lowercase();
694 ///
695 /// assert_eq!("grÜße, jÜrgen ❤", s);
696 /// ```
697 #[unstable(feature = "osstring_ascii", issue = "70516")]
698 pub fn make_ascii_lowercase(&mut self) {
699 self.inner.make_ascii_lowercase()
700 }
701
702 /// Converts this string to its ASCII upper case equivalent in-place.
703 ///
704 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
705 /// but non-ASCII letters are unchanged.
706 ///
707 /// To return a new uppercased value without modifying the existing one, use
3dfed10e 708 /// [`OsStr::to_ascii_uppercase`].
ba9703b0
XL
709 ///
710 /// # Examples
711 ///
712 /// ```
713 /// #![feature(osstring_ascii)]
714 /// use std::ffi::OsString;
715 ///
716 /// let mut s = OsString::from("Grüße, Jürgen ❤");
717 ///
718 /// s.make_ascii_uppercase();
719 ///
720 /// assert_eq!("GRüßE, JüRGEN ❤", s);
721 /// ```
722 #[unstable(feature = "osstring_ascii", issue = "70516")]
723 pub fn make_ascii_uppercase(&mut self) {
724 self.inner.make_ascii_uppercase()
725 }
726
727 /// Returns a copy of this string where each character is mapped to its
728 /// ASCII lower case equivalent.
729 ///
730 /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
731 /// but non-ASCII letters are unchanged.
732 ///
3dfed10e 733 /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`].
ba9703b0
XL
734 ///
735 /// # Examples
736 ///
737 /// ```
738 /// #![feature(osstring_ascii)]
739 /// use std::ffi::OsString;
740 /// let s = OsString::from("Grüße, Jürgen ❤");
741 ///
742 /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
743 /// ```
744 #[unstable(feature = "osstring_ascii", issue = "70516")]
745 pub fn to_ascii_lowercase(&self) -> OsString {
746 OsString::from_inner(self.inner.to_ascii_lowercase())
747 }
748
749 /// Returns a copy of this string where each character is mapped to its
750 /// ASCII upper case equivalent.
751 ///
752 /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
753 /// but non-ASCII letters are unchanged.
754 ///
3dfed10e 755 /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`].
ba9703b0
XL
756 ///
757 /// # Examples
758 ///
759 /// ```
760 /// #![feature(osstring_ascii)]
761 /// use std::ffi::OsString;
762 /// let s = OsString::from("Grüße, Jürgen ❤");
763 ///
764 /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
765 /// ```
766 #[unstable(feature = "osstring_ascii", issue = "70516")]
767 pub fn to_ascii_uppercase(&self) -> OsString {
768 OsString::from_inner(self.inner.to_ascii_uppercase())
769 }
770
771 /// Checks if all characters in this string are within the ASCII range.
772 ///
773 /// # Examples
774 ///
775 /// ```
776 /// #![feature(osstring_ascii)]
777 /// use std::ffi::OsString;
778 ///
779 /// let ascii = OsString::from("hello!\n");
780 /// let non_ascii = OsString::from("Grüße, Jürgen ❤");
781 ///
782 /// assert!(ascii.is_ascii());
783 /// assert!(!non_ascii.is_ascii());
784 /// ```
785 #[unstable(feature = "osstring_ascii", issue = "70516")]
786 pub fn is_ascii(&self) -> bool {
787 self.inner.is_ascii()
788 }
789
790 /// Checks that two strings are an ASCII case-insensitive match.
791 ///
792 /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
793 /// but without allocating and copying temporaries.
794 ///
795 /// # Examples
796 ///
797 /// ```
798 /// #![feature(osstring_ascii)]
799 /// use std::ffi::OsString;
800 ///
801 /// assert!(OsString::from("Ferris").eq_ignore_ascii_case("FERRIS"));
802 /// assert!(OsString::from("Ferrös").eq_ignore_ascii_case("FERRöS"));
803 /// assert!(!OsString::from("Ferrös").eq_ignore_ascii_case("FERRÖS"));
804 /// ```
805 #[unstable(feature = "osstring_ascii", issue = "70516")]
806 pub fn eq_ignore_ascii_case<S: ?Sized + AsRef<OsStr>>(&self, other: &S) -> bool {
807 self.inner.eq_ignore_ascii_case(&other.as_ref().inner)
808 }
85aaf69f
SL
809}
810
8bb4bdeb 811#[stable(feature = "box_from_os_str", since = "1.17.0")]
532ac7d7
XL
812impl From<&OsStr> for Box<OsStr> {
813 fn from(s: &OsStr) -> Box<OsStr> {
ea8adc8c
XL
814 let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
815 unsafe { Box::from_raw(rw) }
8bb4bdeb
XL
816 }
817}
818
f9f354fc
XL
819#[stable(feature = "box_from_cow", since = "1.45.0")]
820impl From<Cow<'_, OsStr>> for Box<OsStr> {
821 #[inline]
822 fn from(cow: Cow<'_, OsStr>) -> Box<OsStr> {
823 match cow {
824 Cow::Borrowed(s) => Box::from(s),
825 Cow::Owned(s) => Box::from(s),
826 }
827 }
828}
829
7cac9316
XL
830#[stable(feature = "os_string_from_box", since = "1.18.0")]
831impl From<Box<OsStr>> for OsString {
416331ca
XL
832 /// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or
833 /// allocating.
cc61c64b
XL
834 fn from(boxed: Box<OsStr>) -> OsString {
835 boxed.into_os_string()
836 }
837}
838
041b39d2
XL
839#[stable(feature = "box_from_os_string", since = "1.20.0")]
840impl From<OsString> for Box<OsStr> {
b7449926 841 /// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
041b39d2
XL
842 fn from(s: OsString) -> Box<OsStr> {
843 s.into_boxed_os_str()
cc61c64b
XL
844 }
845}
846
8faf50e0
XL
847#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
848impl Clone for Box<OsStr> {
849 #[inline]
850 fn clone(&self) -> Self {
851 self.to_os_string().into_boxed_os_str()
852 }
853}
854
2c00a5a8 855#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11 856impl From<OsString> for Arc<OsStr> {
b7449926 857 /// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
ff7c6d11
XL
858 #[inline]
859 fn from(s: OsString) -> Arc<OsStr> {
860 let arc = s.inner.into_arc();
861 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
862 }
863}
864
2c00a5a8 865#[stable(feature = "shared_from_slice2", since = "1.24.0")]
532ac7d7 866impl From<&OsStr> for Arc<OsStr> {
ff7c6d11
XL
867 #[inline]
868 fn from(s: &OsStr) -> Arc<OsStr> {
869 let arc = s.inner.into_arc();
870 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
871 }
872}
873
2c00a5a8 874#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11 875impl From<OsString> for Rc<OsStr> {
b7449926 876 /// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
ff7c6d11
XL
877 #[inline]
878 fn from(s: OsString) -> Rc<OsStr> {
879 let rc = s.inner.into_rc();
880 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
881 }
882}
883
2c00a5a8 884#[stable(feature = "shared_from_slice2", since = "1.24.0")]
532ac7d7 885impl From<&OsStr> for Rc<OsStr> {
ff7c6d11
XL
886 #[inline]
887 fn from(s: &OsStr) -> Rc<OsStr> {
888 let rc = s.inner.into_rc();
889 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
890 }
891}
892
94b46f34
XL
893#[stable(feature = "cow_from_osstr", since = "1.28.0")]
894impl<'a> From<OsString> for Cow<'a, OsStr> {
895 #[inline]
896 fn from(s: OsString) -> Cow<'a, OsStr> {
897 Cow::Owned(s)
898 }
899}
900
901#[stable(feature = "cow_from_osstr", since = "1.28.0")]
902impl<'a> From<&'a OsStr> for Cow<'a, OsStr> {
903 #[inline]
904 fn from(s: &'a OsStr) -> Cow<'a, OsStr> {
905 Cow::Borrowed(s)
906 }
907}
908
909#[stable(feature = "cow_from_osstr", since = "1.28.0")]
910impl<'a> From<&'a OsString> for Cow<'a, OsStr> {
911 #[inline]
912 fn from(s: &'a OsString) -> Cow<'a, OsStr> {
913 Cow::Borrowed(s.as_os_str())
914 }
915}
916
917#[stable(feature = "osstring_from_cow_osstr", since = "1.28.0")]
918impl<'a> From<Cow<'a, OsStr>> for OsString {
919 #[inline]
920 fn from(s: Cow<'a, OsStr>) -> Self {
921 s.into_owned()
922 }
923}
924
8bb4bdeb
XL
925#[stable(feature = "box_default_extra", since = "1.17.0")]
926impl Default for Box<OsStr> {
927 fn default() -> Box<OsStr> {
ea8adc8c
XL
928 let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
929 unsafe { Box::from_raw(rw) }
8bb4bdeb
XL
930 }
931}
932
54a0048b 933#[stable(feature = "osstring_default", since = "1.9.0")]
9fa01778 934impl Default for &OsStr {
9e0c209e 935 /// Creates an empty `OsStr`.
54a0048b 936 #[inline]
9fa01778 937 fn default() -> Self {
54a0048b
SL
938 OsStr::new("")
939 }
940}
941
c34b1796 942#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 943impl PartialEq for OsStr {
60c5eb7d 944 #[inline]
85aaf69f
SL
945 fn eq(&self, other: &OsStr) -> bool {
946 self.bytes().eq(other.bytes())
947 }
948}
949
c34b1796 950#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 951impl PartialEq<str> for OsStr {
60c5eb7d 952 #[inline]
85aaf69f 953 fn eq(&self, other: &str) -> bool {
c34b1796 954 *self == *OsStr::new(other)
85aaf69f
SL
955 }
956}
957
c34b1796 958#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 959impl PartialEq<OsStr> for str {
60c5eb7d 960 #[inline]
85aaf69f 961 fn eq(&self, other: &OsStr) -> bool {
c34b1796 962 *other == *OsStr::new(self)
85aaf69f
SL
963 }
964}
965
c34b1796 966#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
967impl Eq for OsStr {}
968
c34b1796 969#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
970impl PartialOrd for OsStr {
971 #[inline]
972 fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
973 self.bytes().partial_cmp(other.bytes())
974 }
975 #[inline]
dfeec247
XL
976 fn lt(&self, other: &OsStr) -> bool {
977 self.bytes().lt(other.bytes())
978 }
85aaf69f 979 #[inline]
dfeec247
XL
980 fn le(&self, other: &OsStr) -> bool {
981 self.bytes().le(other.bytes())
982 }
85aaf69f 983 #[inline]
dfeec247
XL
984 fn gt(&self, other: &OsStr) -> bool {
985 self.bytes().gt(other.bytes())
986 }
85aaf69f 987 #[inline]
dfeec247
XL
988 fn ge(&self, other: &OsStr) -> bool {
989 self.bytes().ge(other.bytes())
990 }
85aaf69f
SL
991}
992
c34b1796 993#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
994impl PartialOrd<str> for OsStr {
995 #[inline]
996 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
c34b1796 997 self.partial_cmp(OsStr::new(other))
85aaf69f
SL
998 }
999}
1000
1001// FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
1002// have more flexible coherence rules.
1003
c34b1796 1004#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1005impl Ord for OsStr {
1006 #[inline]
dfeec247
XL
1007 fn cmp(&self, other: &OsStr) -> cmp::Ordering {
1008 self.bytes().cmp(other.bytes())
1009 }
85aaf69f
SL
1010}
1011
7453a54e
SL
1012macro_rules! impl_cmp {
1013 ($lhs:ty, $rhs: ty) => {
1014 #[stable(feature = "cmp_os_str", since = "1.8.0")]
1015 impl<'a, 'b> PartialEq<$rhs> for $lhs {
1016 #[inline]
dfeec247
XL
1017 fn eq(&self, other: &$rhs) -> bool {
1018 <OsStr as PartialEq>::eq(self, other)
1019 }
7453a54e
SL
1020 }
1021
1022 #[stable(feature = "cmp_os_str", since = "1.8.0")]
1023 impl<'a, 'b> PartialEq<$lhs> for $rhs {
1024 #[inline]
dfeec247
XL
1025 fn eq(&self, other: &$lhs) -> bool {
1026 <OsStr as PartialEq>::eq(self, other)
1027 }
7453a54e
SL
1028 }
1029
1030 #[stable(feature = "cmp_os_str", since = "1.8.0")]
1031 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
1032 #[inline]
1033 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
1034 <OsStr as PartialOrd>::partial_cmp(self, other)
1035 }
1036 }
1037
1038 #[stable(feature = "cmp_os_str", since = "1.8.0")]
1039 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
1040 #[inline]
1041 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
1042 <OsStr as PartialOrd>::partial_cmp(self, other)
1043 }
1044 }
dfeec247 1045 };
7453a54e
SL
1046}
1047
1048impl_cmp!(OsString, OsStr);
1049impl_cmp!(OsString, &'a OsStr);
1050impl_cmp!(Cow<'a, OsStr>, OsStr);
1051impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
1052impl_cmp!(Cow<'a, OsStr>, OsString);
1053
85aaf69f
SL
1054#[stable(feature = "rust1", since = "1.0.0")]
1055impl Hash for OsStr {
1056 #[inline]
1057 fn hash<H: Hasher>(&self, state: &mut H) {
1058 self.bytes().hash(state)
1059 }
1060}
1061
c34b1796 1062#[stable(feature = "rust1", since = "1.0.0")]
041b39d2 1063impl fmt::Debug for OsStr {
532ac7d7 1064 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
041b39d2
XL
1065 fmt::Debug::fmt(&self.inner, formatter)
1066 }
1067}
1068
1069impl OsStr {
532ac7d7 1070 pub(crate) fn display(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
041b39d2 1071 fmt::Display::fmt(&self.inner, formatter)
85aaf69f
SL
1072 }
1073}
1074
c34b1796 1075#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1076impl Borrow<OsStr> for OsString {
dfeec247
XL
1077 fn borrow(&self) -> &OsStr {
1078 &self[..]
1079 }
85aaf69f
SL
1080}
1081
c34b1796 1082#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1083impl ToOwned for OsStr {
1084 type Owned = OsString;
cc61c64b
XL
1085 fn to_owned(&self) -> OsString {
1086 self.to_os_string()
1087 }
1088 fn clone_into(&self, target: &mut OsString) {
ba9703b0 1089 self.inner.clone_into(&mut target.inner)
cc61c64b 1090 }
85aaf69f
SL
1091}
1092
c34b1796
AL
1093#[stable(feature = "rust1", since = "1.0.0")]
1094impl AsRef<OsStr> for OsStr {
1095 fn as_ref(&self) -> &OsStr {
1096 self
85aaf69f
SL
1097 }
1098}
1099
c34b1796
AL
1100#[stable(feature = "rust1", since = "1.0.0")]
1101impl AsRef<OsStr> for OsString {
dfeec247 1102 #[inline]
c34b1796
AL
1103 fn as_ref(&self) -> &OsStr {
1104 self
1105 }
1106}
1107
1108#[stable(feature = "rust1", since = "1.0.0")]
1109impl AsRef<OsStr> for str {
60c5eb7d 1110 #[inline]
c34b1796 1111 fn as_ref(&self) -> &OsStr {
e9174d1e 1112 OsStr::from_inner(Slice::from_str(self))
c34b1796
AL
1113 }
1114}
1115
1116#[stable(feature = "rust1", since = "1.0.0")]
1117impl AsRef<OsStr> for String {
60c5eb7d 1118 #[inline]
c34b1796 1119 fn as_ref(&self) -> &OsStr {
e9174d1e 1120 (&**self).as_ref()
c34b1796
AL
1121 }
1122}
1123
85aaf69f
SL
1124impl FromInner<Buf> for OsString {
1125 fn from_inner(buf: Buf) -> OsString {
1126 OsString { inner: buf }
1127 }
1128}
1129
1130impl IntoInner<Buf> for OsString {
1131 fn into_inner(self) -> Buf {
1132 self.inner
1133 }
1134}
1135
1136impl AsInner<Slice> for OsStr {
532ac7d7 1137 #[inline]
85aaf69f
SL
1138 fn as_inner(&self) -> &Slice {
1139 &self.inner
1140 }
1141}
7453a54e 1142
f9f354fc
XL
1143#[stable(feature = "osstring_from_str", since = "1.45.0")]
1144impl FromStr for OsString {
1145 type Err = core::convert::Infallible;
1146
1147 fn from_str(s: &str) -> Result<Self, Self::Err> {
1148 Ok(OsString::from(s))
1149 }
1150}