1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use borrow::{Borrow, Cow};
12 use fmt::{self, Debug};
16 use hash::{Hash, Hasher};
18 use sys::os_str::{Buf, Slice};
19 use sys_common::{AsInner, IntoInner, FromInner};
21 /// A type that can represent owned, mutable platform-native strings, but is
22 /// cheaply inter-convertible with Rust strings.
24 /// The need for this type arises from the fact that:
26 /// * On Unix systems, strings are often arbitrary sequences of non-zero
27 /// bytes, in many cases interpreted as UTF-8.
29 /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
30 /// values, interpreted as UTF-16 when it is valid to do so.
32 /// * In Rust, strings are always valid UTF-8, but may contain zeros.
34 /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
35 /// and platform-native string values, and in particular allowing a Rust string
36 /// to be converted into an "OS" string with no cost.
38 /// [`OsStr`]: struct.OsStr.html
40 #[stable(feature = "rust1", since = "1.0.0")]
45 /// Slices into OS strings (see [`OsString`]).
47 /// [`OsString`]: struct.OsString.html
48 #[stable(feature = "rust1", since = "1.0.0")]
54 /// Constructs a new empty `OsString`.
59 /// use std::ffi::OsString;
61 /// let os_string = OsString::new();
63 #[stable(feature = "rust1", since = "1.0.0")]
64 pub fn new() -> OsString {
65 OsString { inner: Buf::from_string(String::new()) }
68 /// Converts to an [`OsStr`] slice.
70 /// [`OsStr`]: struct.OsStr.html
75 /// use std::ffi::{OsString, OsStr};
77 /// let os_string = OsString::from("foo");
78 /// let os_str = OsStr::new("foo");
79 /// assert_eq!(os_string.as_os_str(), os_str);
81 #[stable(feature = "rust1", since = "1.0.0")]
82 pub fn as_os_str(&self) -> &OsStr {
86 /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
88 /// On failure, ownership of the original `OsString` is returned.
90 /// [`String`]: ../../std/string/struct.String.html
95 /// use std::ffi::OsString;
97 /// let os_string = OsString::from("foo");
98 /// let string = os_string.into_string();
99 /// assert_eq!(string, Ok(String::from("foo")));
101 #[stable(feature = "rust1", since = "1.0.0")]
102 pub fn into_string(self) -> Result<String, OsString> {
103 self.inner.into_string().map_err(|buf| OsString { inner: buf} )
106 /// Extends the string with the given [`&OsStr`] slice.
108 /// [`&OsStr`]: struct.OsStr.html
113 /// use std::ffi::OsString;
115 /// let mut os_string = OsString::from("foo");
116 /// os_string.push("bar");
117 /// assert_eq!(&os_string, "foobar");
119 #[stable(feature = "rust1", since = "1.0.0")]
120 pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
121 self.inner.push_slice(&s.as_ref().inner)
124 /// Creates a new `OsString` with the given capacity.
126 /// The string will be able to hold exactly `capacity` lenth units of other
127 /// OS strings without reallocating. If `capacity` is 0, the string will not
130 /// See main `OsString` documentation information about encoding.
135 /// use std::ffi::OsString;
137 /// let mut os_string = OsString::with_capacity(10);
138 /// let capacity = os_string.capacity();
140 /// // This push is done without reallocating
141 /// os_string.push("foo");
143 /// assert_eq!(capacity, os_string.capacity());
145 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
146 pub fn with_capacity(capacity: usize) -> OsString {
148 inner: Buf::with_capacity(capacity)
152 /// Truncates the `OsString` to zero length.
157 /// use std::ffi::OsString;
159 /// let mut os_string = OsString::from("foo");
160 /// assert_eq!(&os_string, "foo");
162 /// os_string.clear();
163 /// assert_eq!(&os_string, "");
165 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
166 pub fn clear(&mut self) {
170 /// Returns the capacity this `OsString` can hold without reallocating.
172 /// See `OsString` introduction for information about encoding.
177 /// use std::ffi::OsString;
179 /// let mut os_string = OsString::with_capacity(10);
180 /// assert!(os_string.capacity() >= 10);
182 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
183 pub fn capacity(&self) -> usize {
184 self.inner.capacity()
187 /// Reserves capacity for at least `additional` more capacity to be inserted
188 /// in the given `OsString`.
190 /// The collection may reserve more space to avoid frequent reallocations.
191 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
192 pub fn reserve(&mut self, additional: usize) {
193 self.inner.reserve(additional)
196 /// Reserves the minimum capacity for exactly `additional` more capacity to
197 /// be inserted in the given `OsString`. Does nothing if the capacity is
198 /// already sufficient.
200 /// Note that the allocator may give the collection more space than it
201 /// requests. Therefore capacity can not be relied upon to be precisely
202 /// minimal. Prefer reserve if future insertions are expected.
203 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
204 pub fn reserve_exact(&mut self, additional: usize) {
205 self.inner.reserve_exact(additional)
208 /// Converts this `OsString` into a boxed `OsStr`.
209 #[unstable(feature = "into_boxed_os_str", issue = "40380")]
210 pub fn into_boxed_os_str(self) -> Box<OsStr> {
211 unsafe { mem::transmute(self.inner.into_box()) }
215 #[stable(feature = "rust1", since = "1.0.0")]
216 impl From<String> for OsString {
217 fn from(s: String) -> OsString {
218 OsString { inner: Buf::from_string(s) }
222 #[stable(feature = "rust1", since = "1.0.0")]
223 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
224 fn from(s: &'a T) -> OsString {
225 s.as_ref().to_os_string()
229 #[stable(feature = "rust1", since = "1.0.0")]
230 impl ops::Index<ops::RangeFull> for OsString {
234 fn index(&self, _index: ops::RangeFull) -> &OsStr {
235 OsStr::from_inner(self.inner.as_slice())
239 #[stable(feature = "rust1", since = "1.0.0")]
240 impl ops::Deref for OsString {
244 fn deref(&self) -> &OsStr {
249 #[stable(feature = "osstring_default", since = "1.9.0")]
250 impl Default for OsString {
251 /// Constructs an empty `OsString`.
253 fn default() -> OsString {
258 #[stable(feature = "rust1", since = "1.0.0")]
259 impl Debug for OsString {
260 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
261 fmt::Debug::fmt(&**self, formatter)
265 #[stable(feature = "rust1", since = "1.0.0")]
266 impl PartialEq for OsString {
267 fn eq(&self, other: &OsString) -> bool {
272 #[stable(feature = "rust1", since = "1.0.0")]
273 impl PartialEq<str> for OsString {
274 fn eq(&self, other: &str) -> bool {
279 #[stable(feature = "rust1", since = "1.0.0")]
280 impl PartialEq<OsString> for str {
281 fn eq(&self, other: &OsString) -> bool {
286 #[stable(feature = "rust1", since = "1.0.0")]
287 impl Eq for OsString {}
289 #[stable(feature = "rust1", since = "1.0.0")]
290 impl PartialOrd for OsString {
292 fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
293 (&**self).partial_cmp(&**other)
296 fn lt(&self, other: &OsString) -> bool { &**self < &**other }
298 fn le(&self, other: &OsString) -> bool { &**self <= &**other }
300 fn gt(&self, other: &OsString) -> bool { &**self > &**other }
302 fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
305 #[stable(feature = "rust1", since = "1.0.0")]
306 impl PartialOrd<str> for OsString {
308 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
309 (&**self).partial_cmp(other)
313 #[stable(feature = "rust1", since = "1.0.0")]
314 impl Ord for OsString {
316 fn cmp(&self, other: &OsString) -> cmp::Ordering {
317 (&**self).cmp(&**other)
321 #[stable(feature = "rust1", since = "1.0.0")]
322 impl Hash for OsString {
324 fn hash<H: Hasher>(&self, state: &mut H) {
325 (&**self).hash(state)
330 /// Coerces into an `OsStr` slice.
335 /// use std::ffi::OsStr;
337 /// let os_str = OsStr::new("foo");
339 #[stable(feature = "rust1", since = "1.0.0")]
340 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
344 fn from_inner(inner: &Slice) -> &OsStr {
345 unsafe { mem::transmute(inner) }
348 /// Yields a [`&str`] slice if the `OsStr` is valid Unicode.
350 /// This conversion may entail doing a check for UTF-8 validity.
352 /// [`&str`]: ../../std/primitive.str.html
357 /// use std::ffi::OsStr;
359 /// let os_str = OsStr::new("foo");
360 /// assert_eq!(os_str.to_str(), Some("foo"));
362 #[stable(feature = "rust1", since = "1.0.0")]
363 pub fn to_str(&self) -> Option<&str> {
367 /// Converts an `OsStr` to a [`Cow`]`<`[`str`]`>`.
369 /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
371 /// [`Cow`]: ../../std/borrow/enum.Cow.html
372 /// [`str`]: ../../std/primitive.str.html
376 /// Calling `to_string_lossy` on an `OsStr` with valid unicode:
379 /// use std::ffi::OsStr;
381 /// let os_str = OsStr::new("foo");
382 /// assert_eq!(os_str.to_string_lossy(), "foo");
385 /// Had `os_str` contained invalid unicode, the `to_string_lossy` call might
386 /// have returned `"fo�"`.
387 #[stable(feature = "rust1", since = "1.0.0")]
388 pub fn to_string_lossy(&self) -> Cow<str> {
389 self.inner.to_string_lossy()
392 /// Copies the slice into an owned [`OsString`].
394 /// [`OsString`]: struct.OsString.html
395 #[stable(feature = "rust1", since = "1.0.0")]
396 pub fn to_os_string(&self) -> OsString {
397 OsString { inner: self.inner.to_owned() }
400 /// Checks whether the `OsStr` is empty.
405 /// use std::ffi::OsStr;
407 /// let os_str = OsStr::new("");
408 /// assert!(os_str.is_empty());
410 /// let os_str = OsStr::new("foo");
411 /// assert!(!os_str.is_empty());
413 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
414 pub fn is_empty(&self) -> bool {
415 self.inner.inner.is_empty()
418 /// Returns the length of this `OsStr`.
420 /// Note that this does **not** return the number of bytes in this string
421 /// as, for example, OS strings on Windows are encoded as a list of `u16`
422 /// rather than a list of bytes. This number is simply useful for passing to
423 /// other methods like [`OsString::with_capacity`] to avoid reallocations.
425 /// See `OsStr` introduction for more information about encoding.
427 /// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity
432 /// use std::ffi::OsStr;
434 /// let os_str = OsStr::new("");
435 /// assert_eq!(os_str.len(), 0);
437 /// let os_str = OsStr::new("foo");
438 /// assert_eq!(os_str.len(), 3);
440 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
441 pub fn len(&self) -> usize {
442 self.inner.inner.len()
445 /// Converts a `Box<OsStr>` into an `OsString` without copying or allocating.
446 #[unstable(feature = "into_boxed_os_str", issue = "40380")]
447 pub fn into_os_string(self: Box<OsStr>) -> OsString {
448 let inner: Box<Slice> = unsafe { mem::transmute(self) };
449 OsString { inner: Buf::from_box(inner) }
452 /// Gets the underlying byte representation.
454 /// Note: it is *crucial* that this API is private, to avoid
455 /// revealing the internal, platform-specific encodings.
456 fn bytes(&self) -> &[u8] {
457 unsafe { mem::transmute(&self.inner) }
461 #[stable(feature = "box_from_os_str", since = "1.17.0")]
462 impl<'a> From<&'a OsStr> for Box<OsStr> {
463 fn from(s: &'a OsStr) -> Box<OsStr> {
464 unsafe { mem::transmute(s.inner.into_box()) }
468 #[stable(feature = "os_string_from_box", since = "1.17.0")]
469 impl<'a> From<Box<OsStr>> for OsString {
470 fn from(boxed: Box<OsStr>) -> OsString {
471 boxed.into_os_string()
475 #[stable(feature = "box_from_c_string", since = "1.17.0")]
476 impl Into<Box<OsStr>> for OsString {
477 fn into(self) -> Box<OsStr> {
478 self.into_boxed_os_str()
482 #[stable(feature = "box_default_extra", since = "1.17.0")]
483 impl Default for Box<OsStr> {
484 fn default() -> Box<OsStr> {
485 unsafe { mem::transmute(Slice::empty_box()) }
489 #[stable(feature = "osstring_default", since = "1.9.0")]
490 impl<'a> Default for &'a OsStr {
491 /// Creates an empty `OsStr`.
493 fn default() -> &'a OsStr {
498 #[stable(feature = "rust1", since = "1.0.0")]
499 impl PartialEq for OsStr {
500 fn eq(&self, other: &OsStr) -> bool {
501 self.bytes().eq(other.bytes())
505 #[stable(feature = "rust1", since = "1.0.0")]
506 impl PartialEq<str> for OsStr {
507 fn eq(&self, other: &str) -> bool {
508 *self == *OsStr::new(other)
512 #[stable(feature = "rust1", since = "1.0.0")]
513 impl PartialEq<OsStr> for str {
514 fn eq(&self, other: &OsStr) -> bool {
515 *other == *OsStr::new(self)
519 #[stable(feature = "rust1", since = "1.0.0")]
522 #[stable(feature = "rust1", since = "1.0.0")]
523 impl PartialOrd for OsStr {
525 fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
526 self.bytes().partial_cmp(other.bytes())
529 fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
531 fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
533 fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
535 fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
538 #[stable(feature = "rust1", since = "1.0.0")]
539 impl PartialOrd<str> for OsStr {
541 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
542 self.partial_cmp(OsStr::new(other))
546 // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
547 // have more flexible coherence rules.
549 #[stable(feature = "rust1", since = "1.0.0")]
552 fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
555 macro_rules! impl_cmp {
556 ($lhs:ty, $rhs: ty) => {
557 #[stable(feature = "cmp_os_str", since = "1.8.0")]
558 impl<'a, 'b> PartialEq<$rhs> for $lhs {
560 fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
563 #[stable(feature = "cmp_os_str", since = "1.8.0")]
564 impl<'a, 'b> PartialEq<$lhs> for $rhs {
566 fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
569 #[stable(feature = "cmp_os_str", since = "1.8.0")]
570 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
572 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
573 <OsStr as PartialOrd>::partial_cmp(self, other)
577 #[stable(feature = "cmp_os_str", since = "1.8.0")]
578 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
580 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
581 <OsStr as PartialOrd>::partial_cmp(self, other)
587 impl_cmp!(OsString, OsStr);
588 impl_cmp!(OsString, &'a OsStr);
589 impl_cmp!(Cow<'a, OsStr>, OsStr);
590 impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
591 impl_cmp!(Cow<'a, OsStr>, OsString);
593 #[stable(feature = "rust1", since = "1.0.0")]
594 impl Hash for OsStr {
596 fn hash<H: Hasher>(&self, state: &mut H) {
597 self.bytes().hash(state)
601 #[stable(feature = "rust1", since = "1.0.0")]
602 impl Debug for OsStr {
603 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
604 self.inner.fmt(formatter)
608 #[stable(feature = "rust1", since = "1.0.0")]
609 impl Borrow<OsStr> for OsString {
610 fn borrow(&self) -> &OsStr { &self[..] }
613 #[stable(feature = "rust1", since = "1.0.0")]
614 impl ToOwned for OsStr {
615 type Owned = OsString;
616 fn to_owned(&self) -> OsString { self.to_os_string() }
619 #[stable(feature = "rust1", since = "1.0.0")]
620 impl AsRef<OsStr> for OsStr {
621 fn as_ref(&self) -> &OsStr {
626 #[stable(feature = "rust1", since = "1.0.0")]
627 impl AsRef<OsStr> for OsString {
628 fn as_ref(&self) -> &OsStr {
633 #[stable(feature = "rust1", since = "1.0.0")]
634 impl AsRef<OsStr> for str {
635 fn as_ref(&self) -> &OsStr {
636 OsStr::from_inner(Slice::from_str(self))
640 #[stable(feature = "rust1", since = "1.0.0")]
641 impl AsRef<OsStr> for String {
642 fn as_ref(&self) -> &OsStr {
647 impl FromInner<Buf> for OsString {
648 fn from_inner(buf: Buf) -> OsString {
649 OsString { inner: buf }
653 impl IntoInner<Buf> for OsString {
654 fn into_inner(self) -> Buf {
659 impl AsInner<Slice> for OsStr {
660 fn as_inner(&self) -> &Slice {
668 use sys_common::{AsInner, IntoInner};
671 fn test_os_string_with_capacity() {
672 let os_string = OsString::with_capacity(0);
673 assert_eq!(0, os_string.inner.into_inner().capacity());
675 let os_string = OsString::with_capacity(10);
676 assert_eq!(10, os_string.inner.into_inner().capacity());
678 let mut os_string = OsString::with_capacity(0);
679 os_string.push("abc");
680 assert!(os_string.inner.into_inner().capacity() >= 3);
684 fn test_os_string_clear() {
685 let mut os_string = OsString::from("abc");
686 assert_eq!(3, os_string.inner.as_inner().len());
689 assert_eq!(&os_string, "");
690 assert_eq!(0, os_string.inner.as_inner().len());
694 fn test_os_string_capacity() {
695 let os_string = OsString::with_capacity(0);
696 assert_eq!(0, os_string.capacity());
698 let os_string = OsString::with_capacity(10);
699 assert_eq!(10, os_string.capacity());
701 let mut os_string = OsString::with_capacity(0);
702 os_string.push("abc");
703 assert!(os_string.capacity() >= 3);
707 fn test_os_string_reserve() {
708 let mut os_string = OsString::new();
709 assert_eq!(os_string.capacity(), 0);
711 os_string.reserve(2);
712 assert!(os_string.capacity() >= 2);
718 assert!(os_string.capacity() >= 16);
719 os_string.reserve(16);
720 assert!(os_string.capacity() >= 32);
724 os_string.reserve(16);
725 assert!(os_string.capacity() >= 33)
729 fn test_os_string_reserve_exact() {
730 let mut os_string = OsString::new();
731 assert_eq!(os_string.capacity(), 0);
733 os_string.reserve_exact(2);
734 assert!(os_string.capacity() >= 2);
740 assert!(os_string.capacity() >= 16);
741 os_string.reserve_exact(16);
742 assert!(os_string.capacity() >= 32);
746 os_string.reserve_exact(16);
747 assert!(os_string.capacity() >= 33)
751 fn test_os_string_default() {
752 let os_string: OsString = Default::default();
753 assert_eq!("", &os_string);
757 fn test_os_str_is_empty() {
758 let mut os_string = OsString::new();
759 assert!(os_string.is_empty());
761 os_string.push("abc");
762 assert!(!os_string.is_empty());
765 assert!(os_string.is_empty());
769 fn test_os_str_len() {
770 let mut os_string = OsString::new();
771 assert_eq!(0, os_string.len());
773 os_string.push("abc");
774 assert_eq!(3, os_string.len());
777 assert_eq!(0, os_string.len());
781 fn test_os_str_default() {
782 let os_str: &OsStr = Default::default();
783 assert_eq!("", os_str);
788 let orig = "Hello, world!";
789 let os_str = OsStr::new(orig);
790 let boxed: Box<OsStr> = Box::from(os_str);
791 let os_string = os_str.to_owned().into_boxed_os_str().into_os_string();
792 assert_eq!(os_str, &*boxed);
793 assert_eq!(&*boxed, &*os_string);
794 assert_eq!(&*os_string, os_str);
799 let boxed = <Box<OsStr>>::default();
800 assert!(boxed.is_empty());