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, ToOwned};
12 use fmt::{self, Debug};
17 use hash::{Hash, Hasher};
20 use sys::os_str::{Buf, Slice};
21 use sys_common::{AsInner, IntoInner, FromInner};
23 /// A type that can represent owned, mutable platform-native strings, but is
24 /// cheaply inter-convertible with Rust strings.
26 /// The need for this type arises from the fact that:
28 /// * On Unix systems, strings are often arbitrary sequences of non-zero
29 /// bytes, in many cases interpreted as UTF-8.
31 /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
32 /// values, interpreted as UTF-16 when it is valid to do so.
34 /// * In Rust, strings are always valid UTF-8, but may contain zeros.
36 /// `OsString` and `OsStr` bridge this gap by simultaneously representing Rust
37 /// and platform-native string values, and in particular allowing a Rust string
38 /// to be converted into an "OS" string with no cost.
40 #[stable(feature = "rust1", since = "1.0.0")]
45 /// Slices into OS strings (see `OsString`).
46 #[stable(feature = "rust1", since = "1.0.0")]
52 /// Constructs a new empty `OsString`.
53 #[stable(feature = "rust1", since = "1.0.0")]
54 pub fn new() -> OsString {
55 OsString { inner: Buf::from_string(String::new()) }
59 fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
60 use os::unix::ffi::OsStringExt;
61 Some(OsString::from_vec(vec))
65 fn _from_bytes(vec: Vec<u8>) -> Option<OsString> {
66 String::from_utf8(vec).ok().map(OsString::from)
69 /// Converts to an `OsStr` slice.
70 #[stable(feature = "rust1", since = "1.0.0")]
71 pub fn as_os_str(&self) -> &OsStr {
75 /// Converts the `OsString` into a `String` if it contains valid Unicode data.
77 /// On failure, ownership of the original `OsString` is returned.
78 #[stable(feature = "rust1", since = "1.0.0")]
79 pub fn into_string(self) -> Result<String, OsString> {
80 self.inner.into_string().map_err(|buf| OsString { inner: buf} )
83 /// Extends the string with the given `&OsStr` slice.
84 #[stable(feature = "rust1", since = "1.0.0")]
85 pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
86 self.inner.push_slice(&s.as_ref().inner)
89 /// Creates a new `OsString` with the given capacity.
91 /// The string will be able to hold exactly `capacity` lenth units of other
92 /// OS strings without reallocating. If `capacity` is 0, the string will not
95 /// See main `OsString` documentation information about encoding.
96 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
97 pub fn with_capacity(capacity: usize) -> OsString {
99 inner: Buf::with_capacity(capacity)
103 /// Truncates the `OsString` to zero length.
104 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
105 pub fn clear(&mut self) {
109 /// Returns the capacity this `OsString` can hold without reallocating.
111 /// See `OsString` introduction for information about encoding.
112 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
113 pub fn capacity(&self) -> usize {
114 self.inner.capacity()
117 /// Reserves capacity for at least `additional` more capacity to be inserted
118 /// in the given `OsString`.
120 /// The collection may reserve more space to avoid frequent reallocations.
121 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
122 pub fn reserve(&mut self, additional: usize) {
123 self.inner.reserve(additional)
126 /// Reserves the minimum capacity for exactly `additional` more capacity to
127 /// be inserted in the given `OsString`. Does nothing if the capacity is
128 /// already sufficient.
130 /// Note that the allocator may give the collection more space than it
131 /// requests. Therefore capacity can not be relied upon to be precisely
132 /// minimal. Prefer reserve if future insertions are expected.
133 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
134 pub fn reserve_exact(&mut self, additional: usize) {
135 self.inner.reserve_exact(additional)
139 #[stable(feature = "rust1", since = "1.0.0")]
140 impl From<String> for OsString {
141 fn from(s: String) -> OsString {
142 OsString { inner: Buf::from_string(s) }
146 #[stable(feature = "rust1", since = "1.0.0")]
147 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
148 fn from(s: &'a T) -> OsString {
149 s.as_ref().to_os_string()
153 #[stable(feature = "rust1", since = "1.0.0")]
154 impl ops::Index<ops::RangeFull> for OsString {
158 fn index(&self, _index: ops::RangeFull) -> &OsStr {
159 OsStr::from_inner(self.inner.as_slice())
163 #[stable(feature = "rust1", since = "1.0.0")]
164 impl ops::Deref for OsString {
168 fn deref(&self) -> &OsStr {
173 #[stable(feature = "osstring_default", since = "1.9.0")]
174 impl Default for OsString {
176 fn default() -> OsString {
181 #[stable(feature = "rust1", since = "1.0.0")]
182 impl Debug for OsString {
183 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
184 fmt::Debug::fmt(&**self, formatter)
188 #[stable(feature = "rust1", since = "1.0.0")]
189 impl PartialEq for OsString {
190 fn eq(&self, other: &OsString) -> bool {
195 #[stable(feature = "rust1", since = "1.0.0")]
196 impl PartialEq<str> for OsString {
197 fn eq(&self, other: &str) -> bool {
202 #[stable(feature = "rust1", since = "1.0.0")]
203 impl PartialEq<OsString> for str {
204 fn eq(&self, other: &OsString) -> bool {
209 #[stable(feature = "rust1", since = "1.0.0")]
210 impl Eq for OsString {}
212 #[stable(feature = "rust1", since = "1.0.0")]
213 impl PartialOrd for OsString {
215 fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
216 (&**self).partial_cmp(&**other)
219 fn lt(&self, other: &OsString) -> bool { &**self < &**other }
221 fn le(&self, other: &OsString) -> bool { &**self <= &**other }
223 fn gt(&self, other: &OsString) -> bool { &**self > &**other }
225 fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
228 #[stable(feature = "rust1", since = "1.0.0")]
229 impl PartialOrd<str> for OsString {
231 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
232 (&**self).partial_cmp(other)
236 #[stable(feature = "rust1", since = "1.0.0")]
237 impl Ord for OsString {
239 fn cmp(&self, other: &OsString) -> cmp::Ordering {
240 (&**self).cmp(&**other)
244 #[stable(feature = "rust1", since = "1.0.0")]
245 impl Hash for OsString {
247 fn hash<H: Hasher>(&self, state: &mut H) {
248 (&**self).hash(state)
253 /// Coerces into an `OsStr` slice.
258 /// use std::ffi::OsStr;
260 /// let os_str = OsStr::new("foo");
262 #[stable(feature = "rust1", since = "1.0.0")]
263 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
267 fn from_inner(inner: &Slice) -> &OsStr {
268 unsafe { mem::transmute(inner) }
271 /// Yields a `&str` slice if the `OsStr` is valid Unicode.
273 /// This conversion may entail doing a check for UTF-8 validity.
274 #[stable(feature = "rust1", since = "1.0.0")]
275 pub fn to_str(&self) -> Option<&str> {
279 /// Converts an `OsStr` to a `Cow<str>`.
281 /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
282 #[stable(feature = "rust1", since = "1.0.0")]
283 pub fn to_string_lossy(&self) -> Cow<str> {
284 self.inner.to_string_lossy()
287 /// Copies the slice into an owned `OsString`.
288 #[stable(feature = "rust1", since = "1.0.0")]
289 pub fn to_os_string(&self) -> OsString {
290 OsString { inner: self.inner.to_owned() }
293 /// Checks whether the `OsStr` is empty.
298 /// use std::ffi::OsStr;
300 /// let os_str = OsStr::new("");
301 /// assert!(os_str.is_empty());
303 /// let os_str = OsStr::new("foo");
304 /// assert!(!os_str.is_empty());
306 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
307 pub fn is_empty(&self) -> bool {
308 self.inner.inner.is_empty()
311 /// Returns the length of this `OsStr`.
313 /// Note that this does **not** return the number of bytes in this string
314 /// as, for example, OS strings on Windows are encoded as a list of `u16`
315 /// rather than a list of bytes. This number is simply useful for passing to
316 /// other methods like `OsString::with_capacity` to avoid reallocations.
318 /// See `OsStr` introduction for more information about encoding.
323 /// use std::ffi::OsStr;
325 /// let os_str = OsStr::new("");
326 /// assert_eq!(os_str.len(), 0);
328 /// let os_str = OsStr::new("foo");
329 /// assert_eq!(os_str.len(), 3);
331 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
332 pub fn len(&self) -> usize {
333 self.inner.inner.len()
336 /// Gets the underlying byte representation.
338 /// Note: it is *crucial* that this API is private, to avoid
339 /// revealing the internal, platform-specific encodings.
340 fn bytes(&self) -> &[u8] {
341 unsafe { mem::transmute(&self.inner) }
345 #[stable(feature = "osstring_default", since = "1.9.0")]
346 impl<'a> Default for &'a OsStr {
348 fn default() -> &'a OsStr {
353 #[stable(feature = "rust1", since = "1.0.0")]
354 impl PartialEq for OsStr {
355 fn eq(&self, other: &OsStr) -> bool {
356 self.bytes().eq(other.bytes())
360 #[stable(feature = "rust1", since = "1.0.0")]
361 impl PartialEq<str> for OsStr {
362 fn eq(&self, other: &str) -> bool {
363 *self == *OsStr::new(other)
367 #[stable(feature = "rust1", since = "1.0.0")]
368 impl PartialEq<OsStr> for str {
369 fn eq(&self, other: &OsStr) -> bool {
370 *other == *OsStr::new(self)
374 #[stable(feature = "rust1", since = "1.0.0")]
377 #[stable(feature = "rust1", since = "1.0.0")]
378 impl PartialOrd for OsStr {
380 fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
381 self.bytes().partial_cmp(other.bytes())
384 fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
386 fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
388 fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
390 fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
393 #[stable(feature = "rust1", since = "1.0.0")]
394 impl PartialOrd<str> for OsStr {
396 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
397 self.partial_cmp(OsStr::new(other))
401 // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
402 // have more flexible coherence rules.
404 #[stable(feature = "rust1", since = "1.0.0")]
407 fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
410 macro_rules! impl_cmp {
411 ($lhs:ty, $rhs: ty) => {
412 #[stable(feature = "cmp_os_str", since = "1.8.0")]
413 impl<'a, 'b> PartialEq<$rhs> for $lhs {
415 fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
418 #[stable(feature = "cmp_os_str", since = "1.8.0")]
419 impl<'a, 'b> PartialEq<$lhs> for $rhs {
421 fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
424 #[stable(feature = "cmp_os_str", since = "1.8.0")]
425 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
427 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
428 <OsStr as PartialOrd>::partial_cmp(self, other)
432 #[stable(feature = "cmp_os_str", since = "1.8.0")]
433 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
435 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
436 <OsStr as PartialOrd>::partial_cmp(self, other)
442 impl_cmp!(OsString, OsStr);
443 impl_cmp!(OsString, &'a OsStr);
444 impl_cmp!(Cow<'a, OsStr>, OsStr);
445 impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
446 impl_cmp!(Cow<'a, OsStr>, OsString);
448 #[stable(feature = "rust1", since = "1.0.0")]
449 impl Hash for OsStr {
451 fn hash<H: Hasher>(&self, state: &mut H) {
452 self.bytes().hash(state)
456 #[stable(feature = "rust1", since = "1.0.0")]
457 impl Debug for OsStr {
458 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
459 self.inner.fmt(formatter)
463 #[stable(feature = "rust1", since = "1.0.0")]
464 impl Borrow<OsStr> for OsString {
465 fn borrow(&self) -> &OsStr { &self[..] }
468 #[stable(feature = "rust1", since = "1.0.0")]
469 impl ToOwned for OsStr {
470 type Owned = OsString;
471 fn to_owned(&self) -> OsString { self.to_os_string() }
474 #[stable(feature = "rust1", since = "1.0.0")]
475 impl AsRef<OsStr> for OsStr {
476 fn as_ref(&self) -> &OsStr {
481 #[stable(feature = "rust1", since = "1.0.0")]
482 impl AsRef<OsStr> for OsString {
483 fn as_ref(&self) -> &OsStr {
488 #[stable(feature = "rust1", since = "1.0.0")]
489 impl AsRef<OsStr> for str {
490 fn as_ref(&self) -> &OsStr {
491 OsStr::from_inner(Slice::from_str(self))
495 #[stable(feature = "rust1", since = "1.0.0")]
496 impl AsRef<OsStr> for String {
497 fn as_ref(&self) -> &OsStr {
502 impl FromInner<Buf> for OsString {
503 fn from_inner(buf: Buf) -> OsString {
504 OsString { inner: buf }
508 impl IntoInner<Buf> for OsString {
509 fn into_inner(self) -> Buf {
514 impl AsInner<Slice> for OsStr {
515 fn as_inner(&self) -> &Slice {
523 use sys_common::{AsInner, IntoInner};
526 fn test_os_string_with_capacity() {
527 let os_string = OsString::with_capacity(0);
528 assert_eq!(0, os_string.inner.into_inner().capacity());
530 let os_string = OsString::with_capacity(10);
531 assert_eq!(10, os_string.inner.into_inner().capacity());
533 let mut os_string = OsString::with_capacity(0);
534 os_string.push("abc");
535 assert!(os_string.inner.into_inner().capacity() >= 3);
539 fn test_os_string_clear() {
540 let mut os_string = OsString::from("abc");
541 assert_eq!(3, os_string.inner.as_inner().len());
544 assert_eq!(&os_string, "");
545 assert_eq!(0, os_string.inner.as_inner().len());
549 fn test_os_string_capacity() {
550 let os_string = OsString::with_capacity(0);
551 assert_eq!(0, os_string.capacity());
553 let os_string = OsString::with_capacity(10);
554 assert_eq!(10, os_string.capacity());
556 let mut os_string = OsString::with_capacity(0);
557 os_string.push("abc");
558 assert!(os_string.capacity() >= 3);
562 fn test_os_string_reserve() {
563 let mut os_string = OsString::new();
564 assert_eq!(os_string.capacity(), 0);
566 os_string.reserve(2);
567 assert!(os_string.capacity() >= 2);
573 assert!(os_string.capacity() >= 16);
574 os_string.reserve(16);
575 assert!(os_string.capacity() >= 32);
579 os_string.reserve(16);
580 assert!(os_string.capacity() >= 33)
584 fn test_os_string_reserve_exact() {
585 let mut os_string = OsString::new();
586 assert_eq!(os_string.capacity(), 0);
588 os_string.reserve_exact(2);
589 assert!(os_string.capacity() >= 2);
595 assert!(os_string.capacity() >= 16);
596 os_string.reserve_exact(16);
597 assert!(os_string.capacity() >= 32);
601 os_string.reserve_exact(16);
602 assert!(os_string.capacity() >= 33)
606 fn test_os_string_default() {
607 let os_string: OsString = Default::default();
608 assert_eq!("", &os_string);
612 fn test_os_str_is_empty() {
613 let mut os_string = OsString::new();
614 assert!(os_string.is_empty());
616 os_string.push("abc");
617 assert!(!os_string.is_empty());
620 assert!(os_string.is_empty());
624 fn test_os_str_len() {
625 let mut os_string = OsString::new();
626 assert_eq!(0, os_string.len());
628 os_string.push("abc");
629 assert_eq!(3, os_string.len());
632 assert_eq!(0, os_string.len());
636 fn test_os_str_default() {
637 let os_str: &OsStr = Default::default();
638 assert_eq!("", os_str);