1 use borrow::{Borrow, Cow};
5 use hash::{Hash, Hasher};
9 use sys::os_str::{Buf, Slice};
10 use sys_common::{AsInner, IntoInner, FromInner};
12 /// A type that can represent owned, mutable platform-native strings, but is
13 /// cheaply inter-convertible with Rust strings.
15 /// The need for this type arises from the fact that:
17 /// * On Unix systems, strings are often arbitrary sequences of non-zero
18 /// bytes, in many cases interpreted as UTF-8.
20 /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
21 /// values, interpreted as UTF-16 when it is valid to do so.
23 /// * In Rust, strings are always valid UTF-8, which may contain zeros.
25 /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
26 /// and platform-native string values, and in particular allowing a Rust string
27 /// to be converted into an "OS" string with no cost if possible. A consequence
28 /// of this is that `OsString` instances are *not* `NUL` terminated; in order
29 /// to pass to e.g., Unix system call, you should create a [`CStr`].
31 /// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former
32 /// in each pair are owned strings; the latter are borrowed
35 /// Note, `OsString` and `OsStr` internally do not necessarily hold strings in
36 /// the form native to the platform; While on Unix, strings are stored as a
37 /// sequence of 8-bit values, on Windows, where strings are 16-bit value based
38 /// as just discussed, strings are also actually stored as a sequence of 8-bit
39 /// values, encoded in a less-strict variant of UTF-8. This is useful to
40 /// understand when handling capacity and length values.
42 /// # Creating an `OsString`
44 /// **From a Rust string**: `OsString` implements
45 /// [`From`]`<`[`String`]`>`, so you can use `my_string.from` to
46 /// create an `OsString` from a normal Rust string.
48 /// **From slices:** Just like you can start with an empty Rust
49 /// [`String`] and then [`push_str`][String.push_str] `&str`
50 /// sub-string slices into it, you can create an empty `OsString` with
51 /// the [`new`] method and then push string slices into it with the
54 /// # Extracting a borrowed reference to the whole OS string
56 /// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from
57 /// an `OsString`; this is effectively a borrowed reference to the
62 /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
63 /// the traits which `OsString` implements for [conversions] from/to native representations.
65 /// [`OsStr`]: struct.OsStr.html
66 /// [`&OsStr`]: struct.OsStr.html
67 /// [`CStr`]: struct.CStr.html
68 /// [`From`]: ../convert/trait.From.html
69 /// [`String`]: ../string/struct.String.html
70 /// [`&str`]: ../primitive.str.html
71 /// [`u8`]: ../primitive.u8.html
72 /// [`u16`]: ../primitive.u16.html
73 /// [String.push_str]: ../string/struct.String.html#method.push_str
74 /// [`new`]: #method.new
75 /// [`push`]: #method.push
76 /// [`as_os_str`]: #method.as_os_str
77 /// [conversions]: index.html#conversions
79 #[stable(feature = "rust1", since = "1.0.0")]
84 /// Borrowed reference to an OS string (see [`OsString`]).
86 /// This type represents a borrowed reference to a string in the operating system's preferred
89 /// `&OsStr` is to [`OsString`] as [`&str`] is to [`String`]: the former in each pair are borrowed
90 /// references; the latter are owned strings.
92 /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
93 /// the traits which `OsStr` implements for [conversions] from/to native representations.
95 /// [`OsString`]: struct.OsString.html
96 /// [`&str`]: ../primitive.str.html
97 /// [`String`]: ../string/struct.String.html
98 /// [conversions]: index.html#conversions
99 #[stable(feature = "rust1", since = "1.0.0")]
105 /// Constructs a new empty `OsString`.
110 /// use std::ffi::OsString;
112 /// let os_string = OsString::new();
114 #[stable(feature = "rust1", since = "1.0.0")]
115 pub fn new() -> OsString {
116 OsString { inner: Buf::from_string(String::new()) }
119 /// Converts to an [`OsStr`] slice.
121 /// [`OsStr`]: struct.OsStr.html
126 /// use std::ffi::{OsString, OsStr};
128 /// let os_string = OsString::from("foo");
129 /// let os_str = OsStr::new("foo");
130 /// assert_eq!(os_string.as_os_str(), os_str);
132 #[stable(feature = "rust1", since = "1.0.0")]
133 pub fn as_os_str(&self) -> &OsStr {
137 /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
139 /// On failure, ownership of the original `OsString` is returned.
141 /// [`String`]: ../../std/string/struct.String.html
146 /// use std::ffi::OsString;
148 /// let os_string = OsString::from("foo");
149 /// let string = os_string.into_string();
150 /// assert_eq!(string, Ok(String::from("foo")));
152 #[stable(feature = "rust1", since = "1.0.0")]
153 pub fn into_string(self) -> Result<String, OsString> {
154 self.inner.into_string().map_err(|buf| OsString { inner: buf} )
157 /// Extends the string with the given [`&OsStr`] slice.
159 /// [`&OsStr`]: struct.OsStr.html
164 /// use std::ffi::OsString;
166 /// let mut os_string = OsString::from("foo");
167 /// os_string.push("bar");
168 /// assert_eq!(&os_string, "foobar");
170 #[stable(feature = "rust1", since = "1.0.0")]
171 pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
172 self.inner.push_slice(&s.as_ref().inner)
175 /// Creates a new `OsString` with the given capacity.
177 /// The string will be able to hold exactly `capacity` length units of other
178 /// OS strings without reallocating. If `capacity` is 0, the string will not
181 /// See main `OsString` documentation information about encoding.
186 /// use std::ffi::OsString;
188 /// let mut os_string = OsString::with_capacity(10);
189 /// let capacity = os_string.capacity();
191 /// // This push is done without reallocating
192 /// os_string.push("foo");
194 /// assert_eq!(capacity, os_string.capacity());
196 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
197 pub fn with_capacity(capacity: usize) -> OsString {
199 inner: Buf::with_capacity(capacity)
203 /// Truncates the `OsString` to zero length.
208 /// use std::ffi::OsString;
210 /// let mut os_string = OsString::from("foo");
211 /// assert_eq!(&os_string, "foo");
213 /// os_string.clear();
214 /// assert_eq!(&os_string, "");
216 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
217 pub fn clear(&mut self) {
221 /// Returns the capacity this `OsString` can hold without reallocating.
223 /// See `OsString` introduction for information about encoding.
228 /// use std::ffi::OsString;
230 /// let mut os_string = OsString::with_capacity(10);
231 /// assert!(os_string.capacity() >= 10);
233 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
234 pub fn capacity(&self) -> usize {
235 self.inner.capacity()
238 /// Reserves capacity for at least `additional` more capacity to be inserted
239 /// in the given `OsString`.
241 /// The collection may reserve more space to avoid frequent reallocations.
246 /// use std::ffi::OsString;
248 /// let mut s = OsString::new();
250 /// assert!(s.capacity() >= 10);
252 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
253 pub fn reserve(&mut self, additional: usize) {
254 self.inner.reserve(additional)
257 /// Reserves the minimum capacity for exactly `additional` more capacity to
258 /// be inserted in the given `OsString`. Does nothing if the capacity is
259 /// already sufficient.
261 /// Note that the allocator may give the collection more space than it
262 /// requests. Therefore capacity can not be relied upon to be precisely
263 /// minimal. Prefer reserve if future insertions are expected.
268 /// use std::ffi::OsString;
270 /// let mut s = OsString::new();
271 /// s.reserve_exact(10);
272 /// assert!(s.capacity() >= 10);
274 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
275 pub fn reserve_exact(&mut self, additional: usize) {
276 self.inner.reserve_exact(additional)
279 /// Shrinks the capacity of the `OsString` to match its length.
284 /// use std::ffi::OsString;
286 /// let mut s = OsString::from("foo");
289 /// assert!(s.capacity() >= 100);
291 /// s.shrink_to_fit();
292 /// assert_eq!(3, s.capacity());
294 #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
295 pub fn shrink_to_fit(&mut self) {
296 self.inner.shrink_to_fit()
299 /// Shrinks the capacity of the `OsString` with a lower bound.
301 /// The capacity will remain at least as large as both the length
302 /// and the supplied value.
304 /// Panics if the current capacity is smaller than the supplied
305 /// minimum capacity.
310 /// #![feature(shrink_to)]
311 /// use std::ffi::OsString;
313 /// let mut s = OsString::from("foo");
316 /// assert!(s.capacity() >= 100);
319 /// assert!(s.capacity() >= 10);
321 /// assert!(s.capacity() >= 3);
324 #[unstable(feature = "shrink_to", reason = "new API", issue="56431")]
325 pub fn shrink_to(&mut self, min_capacity: usize) {
326 self.inner.shrink_to(min_capacity)
329 /// Converts this `OsString` into a boxed [`OsStr`].
331 /// [`OsStr`]: struct.OsStr.html
336 /// use std::ffi::{OsString, OsStr};
338 /// let s = OsString::from("hello");
340 /// let b: Box<OsStr> = s.into_boxed_os_str();
342 #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
343 pub fn into_boxed_os_str(self) -> Box<OsStr> {
344 let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
345 unsafe { Box::from_raw(rw) }
349 #[stable(feature = "rust1", since = "1.0.0")]
350 impl From<String> for OsString {
351 /// Converts a [`String`] into a [`OsString`].
353 /// The conversion copies the data, and includes an allocation on the heap.
354 fn from(s: String) -> OsString {
355 OsString { inner: Buf::from_string(s) }
359 #[stable(feature = "rust1", since = "1.0.0")]
360 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
361 fn from(s: &'a T) -> OsString {
362 s.as_ref().to_os_string()
366 #[stable(feature = "rust1", since = "1.0.0")]
367 impl ops::Index<ops::RangeFull> for OsString {
371 fn index(&self, _index: ops::RangeFull) -> &OsStr {
372 OsStr::from_inner(self.inner.as_slice())
376 #[stable(feature = "rust1", since = "1.0.0")]
377 impl ops::Deref for OsString {
381 fn deref(&self) -> &OsStr {
386 #[stable(feature = "osstring_default", since = "1.9.0")]
387 impl Default for OsString {
388 /// Constructs an empty `OsString`.
390 fn default() -> OsString {
395 #[stable(feature = "rust1", since = "1.0.0")]
396 impl fmt::Debug for OsString {
397 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
398 fmt::Debug::fmt(&**self, formatter)
402 #[stable(feature = "rust1", since = "1.0.0")]
403 impl PartialEq for OsString {
404 fn eq(&self, other: &OsString) -> bool {
409 #[stable(feature = "rust1", since = "1.0.0")]
410 impl PartialEq<str> for OsString {
411 fn eq(&self, other: &str) -> bool {
416 #[stable(feature = "rust1", since = "1.0.0")]
417 impl PartialEq<OsString> for str {
418 fn eq(&self, other: &OsString) -> bool {
423 #[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
424 impl<'a> PartialEq<&'a str> for OsString {
425 fn eq(&self, other: &&'a str) -> bool {
430 #[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
431 impl<'a> PartialEq<OsString> for &'a str {
432 fn eq(&self, other: &OsString) -> bool {
437 #[stable(feature = "rust1", since = "1.0.0")]
438 impl Eq for OsString {}
440 #[stable(feature = "rust1", since = "1.0.0")]
441 impl PartialOrd for OsString {
443 fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
444 (&**self).partial_cmp(&**other)
447 fn lt(&self, other: &OsString) -> bool { &**self < &**other }
449 fn le(&self, other: &OsString) -> bool { &**self <= &**other }
451 fn gt(&self, other: &OsString) -> bool { &**self > &**other }
453 fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
456 #[stable(feature = "rust1", since = "1.0.0")]
457 impl PartialOrd<str> for OsString {
459 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
460 (&**self).partial_cmp(other)
464 #[stable(feature = "rust1", since = "1.0.0")]
465 impl Ord for OsString {
467 fn cmp(&self, other: &OsString) -> cmp::Ordering {
468 (&**self).cmp(&**other)
472 #[stable(feature = "rust1", since = "1.0.0")]
473 impl Hash for OsString {
475 fn hash<H: Hasher>(&self, state: &mut H) {
476 (&**self).hash(state)
481 /// Coerces into an `OsStr` slice.
486 /// use std::ffi::OsStr;
488 /// let os_str = OsStr::new("foo");
490 #[stable(feature = "rust1", since = "1.0.0")]
491 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
495 fn from_inner(inner: &Slice) -> &OsStr {
496 unsafe { &*(inner as *const Slice as *const OsStr) }
499 /// Yields a [`&str`] slice if the `OsStr` is valid Unicode.
501 /// This conversion may entail doing a check for UTF-8 validity.
503 /// [`&str`]: ../../std/primitive.str.html
508 /// use std::ffi::OsStr;
510 /// let os_str = OsStr::new("foo");
511 /// assert_eq!(os_str.to_str(), Some("foo"));
513 #[stable(feature = "rust1", since = "1.0.0")]
514 pub fn to_str(&self) -> Option<&str> {
518 /// Converts an `OsStr` to a [`Cow`]`<`[`str`]`>`.
520 /// Any non-Unicode sequences are replaced with
521 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
523 /// [`Cow`]: ../../std/borrow/enum.Cow.html
524 /// [`str`]: ../../std/primitive.str.html
525 /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
529 /// Calling `to_string_lossy` on an `OsStr` with invalid unicode:
532 /// // Note, due to differences in how Unix and Windows represent strings,
533 /// // we are forced to complicate this example, setting up example `OsStr`s
534 /// // with different source data and via different platform extensions.
535 /// // Understand that in reality you could end up with such example invalid
536 /// // sequences simply through collecting user command line arguments, for
539 /// #[cfg(any(unix, target_os = "redox"))] {
540 /// use std::ffi::OsStr;
541 /// use std::os::unix::ffi::OsStrExt;
543 /// // Here, the values 0x66 and 0x6f correspond to 'f' and 'o'
544 /// // respectively. The value 0x80 is a lone continuation byte, invalid
545 /// // in a UTF-8 sequence.
546 /// let source = [0x66, 0x6f, 0x80, 0x6f];
547 /// let os_str = OsStr::from_bytes(&source[..]);
549 /// assert_eq!(os_str.to_string_lossy(), "fo�o");
551 /// #[cfg(windows)] {
552 /// use std::ffi::OsString;
553 /// use std::os::windows::prelude::*;
555 /// // Here the values 0x0066 and 0x006f correspond to 'f' and 'o'
556 /// // respectively. The value 0xD800 is a lone surrogate half, invalid
557 /// // in a UTF-16 sequence.
558 /// let source = [0x0066, 0x006f, 0xD800, 0x006f];
559 /// let os_string = OsString::from_wide(&source[..]);
560 /// let os_str = os_string.as_os_str();
562 /// assert_eq!(os_str.to_string_lossy(), "fo�o");
565 #[stable(feature = "rust1", since = "1.0.0")]
566 pub fn to_string_lossy(&self) -> Cow<str> {
567 self.inner.to_string_lossy()
570 /// Copies the slice into an owned [`OsString`].
572 /// [`OsString`]: struct.OsString.html
577 /// use std::ffi::{OsStr, OsString};
579 /// let os_str = OsStr::new("foo");
580 /// let os_string = os_str.to_os_string();
581 /// assert_eq!(os_string, OsString::from("foo"));
583 #[stable(feature = "rust1", since = "1.0.0")]
584 pub fn to_os_string(&self) -> OsString {
585 OsString { inner: self.inner.to_owned() }
588 /// Checks whether the `OsStr` is empty.
593 /// use std::ffi::OsStr;
595 /// let os_str = OsStr::new("");
596 /// assert!(os_str.is_empty());
598 /// let os_str = OsStr::new("foo");
599 /// assert!(!os_str.is_empty());
601 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
602 pub fn is_empty(&self) -> bool {
603 self.inner.inner.is_empty()
606 /// Returns the length of this `OsStr`.
608 /// Note that this does **not** return the number of bytes in the string in
611 /// The length returned is that of the underlying storage used by `OsStr`;
612 /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr`
613 /// store strings in a form best suited for cheap inter-conversion between
614 /// native-platform and Rust string forms, which may differ significantly
615 /// from both of them, including in storage size and encoding.
617 /// This number is simply useful for passing to other methods, like
618 /// [`OsString::with_capacity`] to avoid reallocations.
620 /// [`OsString`]: struct.OsString.html
621 /// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity
626 /// use std::ffi::OsStr;
628 /// let os_str = OsStr::new("");
629 /// assert_eq!(os_str.len(), 0);
631 /// let os_str = OsStr::new("foo");
632 /// assert_eq!(os_str.len(), 3);
634 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
635 pub fn len(&self) -> usize {
636 self.inner.inner.len()
639 /// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating.
641 /// [`Box`]: ../boxed/struct.Box.html
642 /// [`OsString`]: struct.OsString.html
643 #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
644 pub fn into_os_string(self: Box<OsStr>) -> OsString {
645 let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
646 OsString { inner: Buf::from_box(boxed) }
649 /// Gets the underlying byte representation.
651 /// Note: it is *crucial* that this API is private, to avoid
652 /// revealing the internal, platform-specific encodings.
653 fn bytes(&self) -> &[u8] {
654 unsafe { &*(&self.inner as *const _ as *const [u8]) }
658 #[stable(feature = "box_from_os_str", since = "1.17.0")]
659 impl<'a> From<&'a OsStr> for Box<OsStr> {
660 fn from(s: &'a OsStr) -> Box<OsStr> {
661 let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
662 unsafe { Box::from_raw(rw) }
666 #[stable(feature = "os_string_from_box", since = "1.18.0")]
667 impl From<Box<OsStr>> for OsString {
668 /// Converts a `Box<OsStr>` into a `OsString` without copying or allocating.
670 /// [`Box`]: ../boxed/struct.Box.html
671 /// [`OsString`]: ../ffi/struct.OsString.html
672 fn from(boxed: Box<OsStr>) -> OsString {
673 boxed.into_os_string()
677 #[stable(feature = "box_from_os_string", since = "1.20.0")]
678 impl From<OsString> for Box<OsStr> {
679 /// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
681 /// [`Box`]: ../boxed/struct.Box.html
682 /// [`OsString`]: ../ffi/struct.OsString.html
683 fn from(s: OsString) -> Box<OsStr> {
684 s.into_boxed_os_str()
688 #[stable(feature = "more_box_slice_clone", since = "1.29.0")]
689 impl Clone for Box<OsStr> {
691 fn clone(&self) -> Self {
692 self.to_os_string().into_boxed_os_str()
696 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
697 impl From<OsString> for Arc<OsStr> {
698 /// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
700 /// [`Arc`]: ../sync/struct.Arc.html
701 /// [`OsString`]: ../ffi/struct.OsString.html
703 fn from(s: OsString) -> Arc<OsStr> {
704 let arc = s.inner.into_arc();
705 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
709 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
710 impl<'a> From<&'a OsStr> for Arc<OsStr> {
712 fn from(s: &OsStr) -> Arc<OsStr> {
713 let arc = s.inner.into_arc();
714 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
718 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
719 impl From<OsString> for Rc<OsStr> {
720 /// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
722 /// [`Rc`]: ../rc/struct.Rc.html
723 /// [`OsString`]: ../ffi/struct.OsString.html
725 fn from(s: OsString) -> Rc<OsStr> {
726 let rc = s.inner.into_rc();
727 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
731 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
732 impl<'a> From<&'a OsStr> for Rc<OsStr> {
734 fn from(s: &OsStr) -> Rc<OsStr> {
735 let rc = s.inner.into_rc();
736 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
740 #[stable(feature = "cow_from_osstr", since = "1.28.0")]
741 impl<'a> From<OsString> for Cow<'a, OsStr> {
743 fn from(s: OsString) -> Cow<'a, OsStr> {
748 #[stable(feature = "cow_from_osstr", since = "1.28.0")]
749 impl<'a> From<&'a OsStr> for Cow<'a, OsStr> {
751 fn from(s: &'a OsStr) -> Cow<'a, OsStr> {
756 #[stable(feature = "cow_from_osstr", since = "1.28.0")]
757 impl<'a> From<&'a OsString> for Cow<'a, OsStr> {
759 fn from(s: &'a OsString) -> Cow<'a, OsStr> {
760 Cow::Borrowed(s.as_os_str())
764 #[stable(feature = "osstring_from_cow_osstr", since = "1.28.0")]
765 impl<'a> From<Cow<'a, OsStr>> for OsString {
767 fn from(s: Cow<'a, OsStr>) -> Self {
772 #[stable(feature = "box_default_extra", since = "1.17.0")]
773 impl Default for Box<OsStr> {
774 fn default() -> Box<OsStr> {
775 let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
776 unsafe { Box::from_raw(rw) }
780 #[stable(feature = "osstring_default", since = "1.9.0")]
781 impl<'a> Default for &'a OsStr {
782 /// Creates an empty `OsStr`.
784 fn default() -> &'a OsStr {
789 #[stable(feature = "rust1", since = "1.0.0")]
790 impl PartialEq for OsStr {
791 fn eq(&self, other: &OsStr) -> bool {
792 self.bytes().eq(other.bytes())
796 #[stable(feature = "rust1", since = "1.0.0")]
797 impl PartialEq<str> for OsStr {
798 fn eq(&self, other: &str) -> bool {
799 *self == *OsStr::new(other)
803 #[stable(feature = "rust1", since = "1.0.0")]
804 impl PartialEq<OsStr> for str {
805 fn eq(&self, other: &OsStr) -> bool {
806 *other == *OsStr::new(self)
810 #[stable(feature = "rust1", since = "1.0.0")]
813 #[stable(feature = "rust1", since = "1.0.0")]
814 impl PartialOrd for OsStr {
816 fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
817 self.bytes().partial_cmp(other.bytes())
820 fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
822 fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
824 fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
826 fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
829 #[stable(feature = "rust1", since = "1.0.0")]
830 impl PartialOrd<str> for OsStr {
832 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
833 self.partial_cmp(OsStr::new(other))
837 // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
838 // have more flexible coherence rules.
840 #[stable(feature = "rust1", since = "1.0.0")]
843 fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
846 macro_rules! impl_cmp {
847 ($lhs:ty, $rhs: ty) => {
848 #[stable(feature = "cmp_os_str", since = "1.8.0")]
849 impl<'a, 'b> PartialEq<$rhs> for $lhs {
851 fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
854 #[stable(feature = "cmp_os_str", since = "1.8.0")]
855 impl<'a, 'b> PartialEq<$lhs> for $rhs {
857 fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
860 #[stable(feature = "cmp_os_str", since = "1.8.0")]
861 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
863 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
864 <OsStr as PartialOrd>::partial_cmp(self, other)
868 #[stable(feature = "cmp_os_str", since = "1.8.0")]
869 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
871 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
872 <OsStr as PartialOrd>::partial_cmp(self, other)
878 impl_cmp!(OsString, OsStr);
879 impl_cmp!(OsString, &'a OsStr);
880 impl_cmp!(Cow<'a, OsStr>, OsStr);
881 impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
882 impl_cmp!(Cow<'a, OsStr>, OsString);
884 #[stable(feature = "rust1", since = "1.0.0")]
885 impl Hash for OsStr {
887 fn hash<H: Hasher>(&self, state: &mut H) {
888 self.bytes().hash(state)
892 #[stable(feature = "rust1", since = "1.0.0")]
893 impl fmt::Debug for OsStr {
894 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
895 fmt::Debug::fmt(&self.inner, formatter)
900 pub(crate) fn display(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
901 fmt::Display::fmt(&self.inner, formatter)
905 #[stable(feature = "rust1", since = "1.0.0")]
906 impl Borrow<OsStr> for OsString {
907 fn borrow(&self) -> &OsStr { &self[..] }
910 #[stable(feature = "rust1", since = "1.0.0")]
911 impl ToOwned for OsStr {
912 type Owned = OsString;
913 fn to_owned(&self) -> OsString {
916 fn clone_into(&self, target: &mut OsString) {
922 #[stable(feature = "rust1", since = "1.0.0")]
923 impl AsRef<OsStr> for OsStr {
924 fn as_ref(&self) -> &OsStr {
929 #[stable(feature = "rust1", since = "1.0.0")]
930 impl AsRef<OsStr> for OsString {
931 fn as_ref(&self) -> &OsStr {
936 #[stable(feature = "rust1", since = "1.0.0")]
937 impl AsRef<OsStr> for str {
938 fn as_ref(&self) -> &OsStr {
939 OsStr::from_inner(Slice::from_str(self))
943 #[stable(feature = "rust1", since = "1.0.0")]
944 impl AsRef<OsStr> for String {
945 fn as_ref(&self) -> &OsStr {
950 impl FromInner<Buf> for OsString {
951 fn from_inner(buf: Buf) -> OsString {
952 OsString { inner: buf }
956 impl IntoInner<Buf> for OsString {
957 fn into_inner(self) -> Buf {
962 impl AsInner<Slice> for OsStr {
963 fn as_inner(&self) -> &Slice {
971 use sys_common::{AsInner, IntoInner};
977 fn test_os_string_with_capacity() {
978 let os_string = OsString::with_capacity(0);
979 assert_eq!(0, os_string.inner.into_inner().capacity());
981 let os_string = OsString::with_capacity(10);
982 assert_eq!(10, os_string.inner.into_inner().capacity());
984 let mut os_string = OsString::with_capacity(0);
985 os_string.push("abc");
986 assert!(os_string.inner.into_inner().capacity() >= 3);
990 fn test_os_string_clear() {
991 let mut os_string = OsString::from("abc");
992 assert_eq!(3, os_string.inner.as_inner().len());
995 assert_eq!(&os_string, "");
996 assert_eq!(0, os_string.inner.as_inner().len());
1000 fn test_os_string_capacity() {
1001 let os_string = OsString::with_capacity(0);
1002 assert_eq!(0, os_string.capacity());
1004 let os_string = OsString::with_capacity(10);
1005 assert_eq!(10, os_string.capacity());
1007 let mut os_string = OsString::with_capacity(0);
1008 os_string.push("abc");
1009 assert!(os_string.capacity() >= 3);
1013 fn test_os_string_reserve() {
1014 let mut os_string = OsString::new();
1015 assert_eq!(os_string.capacity(), 0);
1017 os_string.reserve(2);
1018 assert!(os_string.capacity() >= 2);
1021 os_string.push("a");
1024 assert!(os_string.capacity() >= 16);
1025 os_string.reserve(16);
1026 assert!(os_string.capacity() >= 32);
1028 os_string.push("a");
1030 os_string.reserve(16);
1031 assert!(os_string.capacity() >= 33)
1035 fn test_os_string_reserve_exact() {
1036 let mut os_string = OsString::new();
1037 assert_eq!(os_string.capacity(), 0);
1039 os_string.reserve_exact(2);
1040 assert!(os_string.capacity() >= 2);
1043 os_string.push("a");
1046 assert!(os_string.capacity() >= 16);
1047 os_string.reserve_exact(16);
1048 assert!(os_string.capacity() >= 32);
1050 os_string.push("a");
1052 os_string.reserve_exact(16);
1053 assert!(os_string.capacity() >= 33)
1057 fn test_os_string_default() {
1058 let os_string: OsString = Default::default();
1059 assert_eq!("", &os_string);
1063 fn test_os_str_is_empty() {
1064 let mut os_string = OsString::new();
1065 assert!(os_string.is_empty());
1067 os_string.push("abc");
1068 assert!(!os_string.is_empty());
1071 assert!(os_string.is_empty());
1075 fn test_os_str_len() {
1076 let mut os_string = OsString::new();
1077 assert_eq!(0, os_string.len());
1079 os_string.push("abc");
1080 assert_eq!(3, os_string.len());
1083 assert_eq!(0, os_string.len());
1087 fn test_os_str_default() {
1088 let os_str: &OsStr = Default::default();
1089 assert_eq!("", os_str);
1094 let orig = "Hello, world!";
1095 let os_str = OsStr::new(orig);
1096 let boxed: Box<OsStr> = Box::from(os_str);
1097 let os_string = os_str.to_owned().into_boxed_os_str().into_os_string();
1098 assert_eq!(os_str, &*boxed);
1099 assert_eq!(&*boxed, &*os_string);
1100 assert_eq!(&*os_string, os_str);
1104 fn boxed_default() {
1105 let boxed = <Box<OsStr>>::default();
1106 assert!(boxed.is_empty());
1110 fn test_os_str_clone_into() {
1111 let mut os_string = OsString::with_capacity(123);
1112 os_string.push("hello");
1113 let os_str = OsStr::new("bonjour");
1114 os_str.clone_into(&mut os_string);
1115 assert_eq!(os_str, os_string);
1116 assert!(os_string.capacity() >= 123);
1121 let orig = "Hello, world!";
1122 let os_str = OsStr::new(orig);
1123 let rc: Rc<OsStr> = Rc::from(os_str);
1124 let arc: Arc<OsStr> = Arc::from(os_str);
1126 assert_eq!(&*rc, os_str);
1127 assert_eq!(&*arc, os_str);
1129 let rc2: Rc<OsStr> = Rc::from(os_str.to_owned());
1130 let arc2: Arc<OsStr> = Arc::from(os_str.to_owned());
1132 assert_eq!(&*rc2, os_str);
1133 assert_eq!(&*arc2, os_str);