]> git.proxmox.com Git - rustc.git/blame - src/libstd/ffi/os_str.rs
New upstream version 1.26.0+dfsg1
[rustc.git] / src / libstd / ffi / os_str.rs
CommitLineData
85aaf69f
SL
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.
4//
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.
10
9e0c209e 11use borrow::{Borrow, Cow};
041b39d2 12use fmt;
85aaf69f
SL
13use ops;
14use cmp;
15use hash::{Hash, Hasher};
ff7c6d11
XL
16use rc::Rc;
17use sync::Arc;
85aaf69f
SL
18
19use sys::os_str::{Buf, Slice};
20use sys_common::{AsInner, IntoInner, FromInner};
85aaf69f 21
9cc50fc6 22/// A type that can represent owned, mutable platform-native strings, but is
54a0048b 23/// cheaply inter-convertible with Rust strings.
9cc50fc6
SL
24///
25/// The need for this type arises from the fact that:
26///
27/// * On Unix systems, strings are often arbitrary sequences of non-zero
28/// bytes, in many cases interpreted as UTF-8.
29///
30/// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
31/// values, interpreted as UTF-16 when it is valid to do so.
32///
041b39d2 33/// * In Rust, strings are always valid UTF-8, which may contain zeros.
9cc50fc6 34///
32a655c1 35/// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
9cc50fc6 36/// and platform-native string values, and in particular allowing a Rust string
abe05a73
XL
37/// to be converted into an "OS" string with no cost if possible.
38///
2c00a5a8 39/// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former
abe05a73
XL
40/// in each pair are owned strings; the latter are borrowed
41/// references.
42///
43/// # Creating an `OsString`
44///
45/// **From a Rust string**: `OsString` implements
46/// [`From`]`<`[`String`]`>`, so you can use `my_string.from` to
47/// create an `OsString` from a normal Rust string.
48///
49/// **From slices:** Just like you can start with an empty Rust
50/// [`String`] and then [`push_str`][String.push_str] `&str`
51/// sub-string slices into it, you can create an empty `OsString` with
52/// the [`new`] method and then push string slices into it with the
53/// [`push`] method.
54///
55/// # Extracting a borrowed reference to the whole OS string
56///
57/// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from
58/// an `OsString`; this is effectively a borrowed reference to the
59/// whole string.
60///
61/// # Conversions
62///
63/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
64/// the traits which `OsString` implements for conversions from/to native representations.
32a655c1
SL
65///
66/// [`OsStr`]: struct.OsStr.html
2c00a5a8 67/// [`&OsStr`]: struct.OsStr.html
abe05a73
XL
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
85aaf69f 77#[derive(Clone)]
c34b1796 78#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
79pub struct OsString {
80 inner: Buf
81}
82
abe05a73
XL
83/// Borrowed reference to an OS string (see [`OsString`]).
84///
85/// This type represents a borrowed reference to a string in the operating system's preferred
86/// representation.
87///
2c00a5a8 88/// `&OsStr` is to [`OsString`] as [`&str`] is to [`String`]: the former in each pair are borrowed
abe05a73
XL
89/// references; the latter are owned strings.
90///
91/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
92/// the traits which `OsStr` implements for conversions from/to native representations.
32a655c1
SL
93///
94/// [`OsString`]: struct.OsString.html
2c00a5a8
XL
95/// [`&str`]: ../primitive.str.html
96/// [`String`]: ../string/struct.String.html
abe05a73 97/// [conversions]: index.html#conversions
c34b1796 98#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
99pub struct OsStr {
100 inner: Slice
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 ///
120 /// [`OsStr`]: struct.OsStr.html
121 ///
122 /// # Examples
123 ///
124 /// ```
125 /// use std::ffi::{OsString, OsStr};
126 ///
127 /// let os_string = OsString::from("foo");
128 /// let os_str = OsStr::new("foo");
129 /// assert_eq!(os_string.as_os_str(), os_str);
130 /// ```
c34b1796
AL
131 #[stable(feature = "rust1", since = "1.0.0")]
132 pub fn as_os_str(&self) -> &OsStr {
133 self
134 }
135
32a655c1 136 /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
85aaf69f
SL
137 ///
138 /// On failure, ownership of the original `OsString` is returned.
32a655c1
SL
139 ///
140 /// [`String`]: ../../std/string/struct.String.html
141 ///
142 /// # Examples
143 ///
144 /// ```
145 /// use std::ffi::OsString;
146 ///
147 /// let os_string = OsString::from("foo");
148 /// let string = os_string.into_string();
149 /// assert_eq!(string, Ok(String::from("foo")));
150 /// ```
c34b1796 151 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
152 pub fn into_string(self) -> Result<String, OsString> {
153 self.inner.into_string().map_err(|buf| OsString { inner: buf} )
154 }
155
32a655c1
SL
156 /// Extends the string with the given [`&OsStr`] slice.
157 ///
158 /// [`&OsStr`]: struct.OsStr.html
159 ///
160 /// # Examples
161 ///
162 /// ```
163 /// use std::ffi::OsString;
164 ///
165 /// let mut os_string = OsString::from("foo");
166 /// os_string.push("bar");
167 /// assert_eq!(&os_string, "foobar");
168 /// ```
c34b1796
AL
169 #[stable(feature = "rust1", since = "1.0.0")]
170 pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
171 self.inner.push_slice(&s.as_ref().inner)
172 }
7453a54e 173
54a0048b
SL
174 /// Creates a new `OsString` with the given capacity.
175 ///
3b2f2976 176 /// The string will be able to hold exactly `capacity` length units of other
54a0048b
SL
177 /// OS strings without reallocating. If `capacity` is 0, the string will not
178 /// allocate.
7453a54e
SL
179 ///
180 /// See main `OsString` documentation information about encoding.
32a655c1
SL
181 ///
182 /// # Examples
183 ///
184 /// ```
185 /// use std::ffi::OsString;
186 ///
187 /// let mut os_string = OsString::with_capacity(10);
188 /// let capacity = os_string.capacity();
189 ///
190 /// // This push is done without reallocating
191 /// os_string.push("foo");
192 ///
193 /// assert_eq!(capacity, os_string.capacity());
194 /// ```
54a0048b 195 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
196 pub fn with_capacity(capacity: usize) -> OsString {
197 OsString {
198 inner: Buf::with_capacity(capacity)
199 }
200 }
201
202 /// Truncates the `OsString` to zero length.
32a655c1
SL
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// use std::ffi::OsString;
208 ///
209 /// let mut os_string = OsString::from("foo");
210 /// assert_eq!(&os_string, "foo");
211 ///
212 /// os_string.clear();
213 /// assert_eq!(&os_string, "");
214 /// ```
54a0048b 215 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
216 pub fn clear(&mut self) {
217 self.inner.clear()
218 }
219
54a0048b 220 /// Returns the capacity this `OsString` can hold without reallocating.
7453a54e
SL
221 ///
222 /// See `OsString` introduction for information about encoding.
32a655c1
SL
223 ///
224 /// # Examples
225 ///
226 /// ```
227 /// use std::ffi::OsString;
228 ///
229 /// let mut os_string = OsString::with_capacity(10);
230 /// assert!(os_string.capacity() >= 10);
231 /// ```
54a0048b 232 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
233 pub fn capacity(&self) -> usize {
234 self.inner.capacity()
235 }
236
54a0048b
SL
237 /// Reserves capacity for at least `additional` more capacity to be inserted
238 /// in the given `OsString`.
239 ///
240 /// The collection may reserve more space to avoid frequent reallocations.
cc61c64b
XL
241 ///
242 /// # Examples
243 ///
244 /// ```
245 /// use std::ffi::OsString;
246 ///
247 /// let mut s = OsString::new();
248 /// s.reserve(10);
249 /// assert!(s.capacity() >= 10);
250 /// ```
54a0048b 251 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
252 pub fn reserve(&mut self, additional: usize) {
253 self.inner.reserve(additional)
254 }
255
54a0048b
SL
256 /// Reserves the minimum capacity for exactly `additional` more capacity to
257 /// be inserted in the given `OsString`. Does nothing if the capacity is
7453a54e
SL
258 /// already sufficient.
259 ///
260 /// Note that the allocator may give the collection more space than it
261 /// requests. Therefore capacity can not be relied upon to be precisely
262 /// minimal. Prefer reserve if future insertions are expected.
cc61c64b
XL
263 ///
264 /// # Examples
265 ///
266 /// ```
267 /// use std::ffi::OsString;
268 ///
269 /// let mut s = OsString::new();
270 /// s.reserve_exact(10);
271 /// assert!(s.capacity() >= 10);
272 /// ```
54a0048b 273 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
274 pub fn reserve_exact(&mut self, additional: usize) {
275 self.inner.reserve_exact(additional)
276 }
8bb4bdeb
XL
277
278 /// Shrinks the capacity of the `OsString` to match its length.
cc61c64b
XL
279 ///
280 /// # Examples
281 ///
282 /// ```
cc61c64b
XL
283 /// use std::ffi::OsString;
284 ///
285 /// let mut s = OsString::from("foo");
286 ///
287 /// s.reserve(100);
288 /// assert!(s.capacity() >= 100);
289 ///
290 /// s.shrink_to_fit();
291 /// assert_eq!(3, s.capacity());
292 /// ```
7cac9316 293 #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
8bb4bdeb
XL
294 pub fn shrink_to_fit(&mut self) {
295 self.inner.shrink_to_fit()
296 }
297
0531ce1d
XL
298 /// Shrinks the capacity of the `OsString` with a lower bound.
299 ///
300 /// The capacity will remain at least as large as both the length
301 /// and the supplied value.
302 ///
303 /// Panics if the current capacity is smaller than the supplied
304 /// minimum capacity.
305 ///
306 /// # Examples
307 ///
308 /// ```
309 /// #![feature(shrink_to)]
310 /// use std::ffi::OsString;
311 ///
312 /// let mut s = OsString::from("foo");
313 ///
314 /// s.reserve(100);
315 /// assert!(s.capacity() >= 100);
316 ///
317 /// s.shrink_to(10);
318 /// assert!(s.capacity() >= 10);
319 /// s.shrink_to(0);
320 /// assert!(s.capacity() >= 3);
321 /// ```
322 #[inline]
323 #[unstable(feature = "shrink_to", reason = "new API", issue="0")]
324 pub fn shrink_to(&mut self, min_capacity: usize) {
325 self.inner.shrink_to(min_capacity)
326 }
327
7cac9316
XL
328 /// Converts this `OsString` into a boxed [`OsStr`].
329 ///
330 /// [`OsStr`]: struct.OsStr.html
cc61c64b
XL
331 ///
332 /// # Examples
333 ///
334 /// ```
cc61c64b
XL
335 /// use std::ffi::{OsString, OsStr};
336 ///
337 /// let s = OsString::from("hello");
338 ///
339 /// let b: Box<OsStr> = s.into_boxed_os_str();
340 /// ```
041b39d2 341 #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
8bb4bdeb 342 pub fn into_boxed_os_str(self) -> Box<OsStr> {
ea8adc8c
XL
343 let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
344 unsafe { Box::from_raw(rw) }
8bb4bdeb 345 }
c34b1796
AL
346}
347
348#[stable(feature = "rust1", since = "1.0.0")]
349impl From<String> for OsString {
350 fn from(s: String) -> OsString {
351 OsString { inner: Buf::from_string(s) }
352 }
353}
354
355#[stable(feature = "rust1", since = "1.0.0")]
356impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
357 fn from(s: &'a T) -> OsString {
358 s.as_ref().to_os_string()
85aaf69f
SL
359 }
360}
361
c34b1796 362#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
363impl ops::Index<ops::RangeFull> for OsString {
364 type Output = OsStr;
365
366 #[inline]
c34b1796 367 fn index(&self, _index: ops::RangeFull) -> &OsStr {
e9174d1e 368 OsStr::from_inner(self.inner.as_slice())
85aaf69f
SL
369 }
370}
371
c34b1796 372#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
373impl ops::Deref for OsString {
374 type Target = OsStr;
375
376 #[inline]
377 fn deref(&self) -> &OsStr {
378 &self[..]
379 }
380}
381
54a0048b
SL
382#[stable(feature = "osstring_default", since = "1.9.0")]
383impl Default for OsString {
9e0c209e 384 /// Constructs an empty `OsString`.
54a0048b
SL
385 #[inline]
386 fn default() -> OsString {
387 OsString::new()
388 }
389}
390
c34b1796 391#[stable(feature = "rust1", since = "1.0.0")]
041b39d2
XL
392impl fmt::Debug for OsString {
393 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
85aaf69f
SL
394 fmt::Debug::fmt(&**self, formatter)
395 }
396}
397
c34b1796 398#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
399impl PartialEq for OsString {
400 fn eq(&self, other: &OsString) -> bool {
401 &**self == &**other
402 }
403}
404
c34b1796 405#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
406impl PartialEq<str> for OsString {
407 fn eq(&self, other: &str) -> bool {
408 &**self == other
409 }
410}
411
c34b1796 412#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
413impl PartialEq<OsString> for str {
414 fn eq(&self, other: &OsString) -> bool {
415 &**other == self
416 }
417}
418
c34b1796 419#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
420impl Eq for OsString {}
421
c34b1796 422#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
423impl PartialOrd for OsString {
424 #[inline]
425 fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> {
426 (&**self).partial_cmp(&**other)
427 }
428 #[inline]
429 fn lt(&self, other: &OsString) -> bool { &**self < &**other }
430 #[inline]
431 fn le(&self, other: &OsString) -> bool { &**self <= &**other }
432 #[inline]
433 fn gt(&self, other: &OsString) -> bool { &**self > &**other }
434 #[inline]
435 fn ge(&self, other: &OsString) -> bool { &**self >= &**other }
436}
437
c34b1796 438#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
439impl PartialOrd<str> for OsString {
440 #[inline]
441 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
442 (&**self).partial_cmp(other)
443 }
444}
445
c34b1796 446#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
447impl Ord for OsString {
448 #[inline]
449 fn cmp(&self, other: &OsString) -> cmp::Ordering {
450 (&**self).cmp(&**other)
451 }
452}
453
85aaf69f
SL
454#[stable(feature = "rust1", since = "1.0.0")]
455impl Hash for OsString {
456 #[inline]
457 fn hash<H: Hasher>(&self, state: &mut H) {
458 (&**self).hash(state)
459 }
460}
461
462impl OsStr {
9346a6ac 463 /// Coerces into an `OsStr` slice.
9e0c209e
SL
464 ///
465 /// # Examples
466 ///
467 /// ```
468 /// use std::ffi::OsStr;
469 ///
470 /// let os_str = OsStr::new("foo");
471 /// ```
c34b1796
AL
472 #[stable(feature = "rust1", since = "1.0.0")]
473 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
474 s.as_ref()
475 }
476
e9174d1e 477 fn from_inner(inner: &Slice) -> &OsStr {
ea8adc8c 478 unsafe { &*(inner as *const Slice as *const OsStr) }
e9174d1e
SL
479 }
480
32a655c1 481 /// Yields a [`&str`] slice if the `OsStr` is valid Unicode.
85aaf69f
SL
482 ///
483 /// This conversion may entail doing a check for UTF-8 validity.
32a655c1
SL
484 ///
485 /// [`&str`]: ../../std/primitive.str.html
486 ///
487 /// # Examples
488 ///
489 /// ```
490 /// use std::ffi::OsStr;
491 ///
492 /// let os_str = OsStr::new("foo");
493 /// assert_eq!(os_str.to_str(), Some("foo"));
494 /// ```
c34b1796 495 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
496 pub fn to_str(&self) -> Option<&str> {
497 self.inner.to_str()
498 }
499
32a655c1 500 /// Converts an `OsStr` to a [`Cow`]`<`[`str`]`>`.
85aaf69f
SL
501 ///
502 /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
32a655c1
SL
503 ///
504 /// [`Cow`]: ../../std/borrow/enum.Cow.html
505 /// [`str`]: ../../std/primitive.str.html
506 ///
507 /// # Examples
508 ///
509 /// Calling `to_string_lossy` on an `OsStr` with valid unicode:
510 ///
511 /// ```
512 /// use std::ffi::OsStr;
513 ///
514 /// let os_str = OsStr::new("foo");
515 /// assert_eq!(os_str.to_string_lossy(), "foo");
516 /// ```
517 ///
518 /// Had `os_str` contained invalid unicode, the `to_string_lossy` call might
519 /// have returned `"fo�"`.
c34b1796
AL
520 #[stable(feature = "rust1", since = "1.0.0")]
521 pub fn to_string_lossy(&self) -> Cow<str> {
85aaf69f
SL
522 self.inner.to_string_lossy()
523 }
524
32a655c1
SL
525 /// Copies the slice into an owned [`OsString`].
526 ///
527 /// [`OsString`]: struct.OsString.html
cc61c64b
XL
528 ///
529 /// # Examples
530 ///
531 /// ```
532 /// use std::ffi::{OsStr, OsString};
533 ///
534 /// let os_str = OsStr::new("foo");
535 /// let os_string = os_str.to_os_string();
536 /// assert_eq!(os_string, OsString::from("foo"));
537 /// ```
c34b1796 538 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
539 pub fn to_os_string(&self) -> OsString {
540 OsString { inner: self.inner.to_owned() }
541 }
542
7453a54e 543 /// Checks whether the `OsStr` is empty.
9e0c209e
SL
544 ///
545 /// # Examples
546 ///
547 /// ```
548 /// use std::ffi::OsStr;
549 ///
550 /// let os_str = OsStr::new("");
551 /// assert!(os_str.is_empty());
552 ///
553 /// let os_str = OsStr::new("foo");
554 /// assert!(!os_str.is_empty());
555 /// ```
54a0048b 556 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
557 pub fn is_empty(&self) -> bool {
558 self.inner.inner.is_empty()
559 }
560
54a0048b
SL
561 /// Returns the length of this `OsStr`.
562 ///
563 /// Note that this does **not** return the number of bytes in this string
7cac9316 564 /// as, for example, OS strings on Windows are encoded as a list of [`u16`]
54a0048b 565 /// rather than a list of bytes. This number is simply useful for passing to
32a655c1 566 /// other methods like [`OsString::with_capacity`] to avoid reallocations.
7453a54e 567 ///
54a0048b 568 /// See `OsStr` introduction for more information about encoding.
9e0c209e 569 ///
7cac9316 570 /// [`u16`]: ../primitive.u16.html
32a655c1
SL
571 /// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity
572 ///
9e0c209e
SL
573 /// # Examples
574 ///
575 /// ```
576 /// use std::ffi::OsStr;
577 ///
578 /// let os_str = OsStr::new("");
579 /// assert_eq!(os_str.len(), 0);
580 ///
581 /// let os_str = OsStr::new("foo");
582 /// assert_eq!(os_str.len(), 3);
583 /// ```
54a0048b 584 #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
7453a54e
SL
585 pub fn len(&self) -> usize {
586 self.inner.inner.len()
587 }
588
7cac9316
XL
589 /// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating.
590 ///
591 /// [`Box`]: ../boxed/struct.Box.html
592 /// [`OsString`]: struct.OsString.html
041b39d2 593 #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
cc61c64b 594 pub fn into_os_string(self: Box<OsStr>) -> OsString {
ea8adc8c
XL
595 let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
596 OsString { inner: Buf::from_box(boxed) }
cc61c64b
XL
597 }
598
9346a6ac 599 /// Gets the underlying byte representation.
85aaf69f
SL
600 ///
601 /// Note: it is *crucial* that this API is private, to avoid
602 /// revealing the internal, platform-specific encodings.
603 fn bytes(&self) -> &[u8] {
ea8adc8c 604 unsafe { &*(&self.inner as *const _ as *const [u8]) }
85aaf69f
SL
605 }
606}
607
8bb4bdeb
XL
608#[stable(feature = "box_from_os_str", since = "1.17.0")]
609impl<'a> From<&'a OsStr> for Box<OsStr> {
610 fn from(s: &'a OsStr) -> Box<OsStr> {
ea8adc8c
XL
611 let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
612 unsafe { Box::from_raw(rw) }
8bb4bdeb
XL
613 }
614}
615
7cac9316
XL
616#[stable(feature = "os_string_from_box", since = "1.18.0")]
617impl From<Box<OsStr>> for OsString {
cc61c64b
XL
618 fn from(boxed: Box<OsStr>) -> OsString {
619 boxed.into_os_string()
620 }
621}
622
041b39d2
XL
623#[stable(feature = "box_from_os_string", since = "1.20.0")]
624impl From<OsString> for Box<OsStr> {
625 fn from(s: OsString) -> Box<OsStr> {
626 s.into_boxed_os_str()
cc61c64b
XL
627 }
628}
629
2c00a5a8 630#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11
XL
631impl From<OsString> for Arc<OsStr> {
632 #[inline]
633 fn from(s: OsString) -> Arc<OsStr> {
634 let arc = s.inner.into_arc();
635 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
636 }
637}
638
2c00a5a8 639#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11
XL
640impl<'a> From<&'a OsStr> for Arc<OsStr> {
641 #[inline]
642 fn from(s: &OsStr) -> Arc<OsStr> {
643 let arc = s.inner.into_arc();
644 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const OsStr) }
645 }
646}
647
2c00a5a8 648#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11
XL
649impl From<OsString> for Rc<OsStr> {
650 #[inline]
651 fn from(s: OsString) -> Rc<OsStr> {
652 let rc = s.inner.into_rc();
653 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
654 }
655}
656
2c00a5a8 657#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11
XL
658impl<'a> From<&'a OsStr> for Rc<OsStr> {
659 #[inline]
660 fn from(s: &OsStr) -> Rc<OsStr> {
661 let rc = s.inner.into_rc();
662 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const OsStr) }
663 }
664}
665
8bb4bdeb
XL
666#[stable(feature = "box_default_extra", since = "1.17.0")]
667impl Default for Box<OsStr> {
668 fn default() -> Box<OsStr> {
ea8adc8c
XL
669 let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
670 unsafe { Box::from_raw(rw) }
8bb4bdeb
XL
671 }
672}
673
54a0048b
SL
674#[stable(feature = "osstring_default", since = "1.9.0")]
675impl<'a> Default for &'a OsStr {
9e0c209e 676 /// Creates an empty `OsStr`.
54a0048b
SL
677 #[inline]
678 fn default() -> &'a OsStr {
679 OsStr::new("")
680 }
681}
682
c34b1796 683#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
684impl PartialEq for OsStr {
685 fn eq(&self, other: &OsStr) -> bool {
686 self.bytes().eq(other.bytes())
687 }
688}
689
c34b1796 690#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
691impl PartialEq<str> for OsStr {
692 fn eq(&self, other: &str) -> bool {
c34b1796 693 *self == *OsStr::new(other)
85aaf69f
SL
694 }
695}
696
c34b1796 697#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
698impl PartialEq<OsStr> for str {
699 fn eq(&self, other: &OsStr) -> bool {
c34b1796 700 *other == *OsStr::new(self)
85aaf69f
SL
701 }
702}
703
c34b1796 704#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
705impl Eq for OsStr {}
706
c34b1796 707#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
708impl PartialOrd for OsStr {
709 #[inline]
710 fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> {
711 self.bytes().partial_cmp(other.bytes())
712 }
713 #[inline]
714 fn lt(&self, other: &OsStr) -> bool { self.bytes().lt(other.bytes()) }
715 #[inline]
716 fn le(&self, other: &OsStr) -> bool { self.bytes().le(other.bytes()) }
717 #[inline]
718 fn gt(&self, other: &OsStr) -> bool { self.bytes().gt(other.bytes()) }
719 #[inline]
720 fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
721}
722
c34b1796 723#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
724impl PartialOrd<str> for OsStr {
725 #[inline]
726 fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
c34b1796 727 self.partial_cmp(OsStr::new(other))
85aaf69f
SL
728 }
729}
730
731// FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we
732// have more flexible coherence rules.
733
c34b1796 734#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
735impl Ord for OsStr {
736 #[inline]
737 fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
738}
739
7453a54e
SL
740macro_rules! impl_cmp {
741 ($lhs:ty, $rhs: ty) => {
742 #[stable(feature = "cmp_os_str", since = "1.8.0")]
743 impl<'a, 'b> PartialEq<$rhs> for $lhs {
744 #[inline]
745 fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
746 }
747
748 #[stable(feature = "cmp_os_str", since = "1.8.0")]
749 impl<'a, 'b> PartialEq<$lhs> for $rhs {
750 #[inline]
751 fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
752 }
753
754 #[stable(feature = "cmp_os_str", since = "1.8.0")]
755 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
756 #[inline]
757 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
758 <OsStr as PartialOrd>::partial_cmp(self, other)
759 }
760 }
761
762 #[stable(feature = "cmp_os_str", since = "1.8.0")]
763 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
764 #[inline]
765 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
766 <OsStr as PartialOrd>::partial_cmp(self, other)
767 }
768 }
769 }
770}
771
772impl_cmp!(OsString, OsStr);
773impl_cmp!(OsString, &'a OsStr);
774impl_cmp!(Cow<'a, OsStr>, OsStr);
775impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
776impl_cmp!(Cow<'a, OsStr>, OsString);
777
85aaf69f
SL
778#[stable(feature = "rust1", since = "1.0.0")]
779impl Hash for OsStr {
780 #[inline]
781 fn hash<H: Hasher>(&self, state: &mut H) {
782 self.bytes().hash(state)
783 }
784}
785
c34b1796 786#[stable(feature = "rust1", since = "1.0.0")]
041b39d2
XL
787impl fmt::Debug for OsStr {
788 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
789 fmt::Debug::fmt(&self.inner, formatter)
790 }
791}
792
793impl OsStr {
794 pub(crate) fn display(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
795 fmt::Display::fmt(&self.inner, formatter)
85aaf69f
SL
796 }
797}
798
c34b1796 799#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
800impl Borrow<OsStr> for OsString {
801 fn borrow(&self) -> &OsStr { &self[..] }
802}
803
c34b1796 804#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
805impl ToOwned for OsStr {
806 type Owned = OsString;
cc61c64b
XL
807 fn to_owned(&self) -> OsString {
808 self.to_os_string()
809 }
810 fn clone_into(&self, target: &mut OsString) {
811 target.clear();
812 target.push(self);
813 }
85aaf69f
SL
814}
815
c34b1796
AL
816#[stable(feature = "rust1", since = "1.0.0")]
817impl AsRef<OsStr> for OsStr {
818 fn as_ref(&self) -> &OsStr {
819 self
85aaf69f
SL
820 }
821}
822
c34b1796
AL
823#[stable(feature = "rust1", since = "1.0.0")]
824impl AsRef<OsStr> for OsString {
825 fn as_ref(&self) -> &OsStr {
826 self
827 }
828}
829
830#[stable(feature = "rust1", since = "1.0.0")]
831impl AsRef<OsStr> for str {
832 fn as_ref(&self) -> &OsStr {
e9174d1e 833 OsStr::from_inner(Slice::from_str(self))
c34b1796
AL
834 }
835}
836
837#[stable(feature = "rust1", since = "1.0.0")]
838impl AsRef<OsStr> for String {
839 fn as_ref(&self) -> &OsStr {
e9174d1e 840 (&**self).as_ref()
c34b1796
AL
841 }
842}
843
85aaf69f
SL
844impl FromInner<Buf> for OsString {
845 fn from_inner(buf: Buf) -> OsString {
846 OsString { inner: buf }
847 }
848}
849
850impl IntoInner<Buf> for OsString {
851 fn into_inner(self) -> Buf {
852 self.inner
853 }
854}
855
856impl AsInner<Slice> for OsStr {
857 fn as_inner(&self) -> &Slice {
858 &self.inner
859 }
860}
7453a54e
SL
861
862#[cfg(test)]
863mod tests {
864 use super::*;
865 use sys_common::{AsInner, IntoInner};
866
ff7c6d11
XL
867 use rc::Rc;
868 use sync::Arc;
869
7453a54e
SL
870 #[test]
871 fn test_os_string_with_capacity() {
872 let os_string = OsString::with_capacity(0);
873 assert_eq!(0, os_string.inner.into_inner().capacity());
874
875 let os_string = OsString::with_capacity(10);
876 assert_eq!(10, os_string.inner.into_inner().capacity());
877
878 let mut os_string = OsString::with_capacity(0);
879 os_string.push("abc");
880 assert!(os_string.inner.into_inner().capacity() >= 3);
881 }
882
883 #[test]
884 fn test_os_string_clear() {
885 let mut os_string = OsString::from("abc");
886 assert_eq!(3, os_string.inner.as_inner().len());
887
888 os_string.clear();
889 assert_eq!(&os_string, "");
890 assert_eq!(0, os_string.inner.as_inner().len());
891 }
892
893 #[test]
894 fn test_os_string_capacity() {
895 let os_string = OsString::with_capacity(0);
896 assert_eq!(0, os_string.capacity());
897
898 let os_string = OsString::with_capacity(10);
899 assert_eq!(10, os_string.capacity());
900
901 let mut os_string = OsString::with_capacity(0);
902 os_string.push("abc");
903 assert!(os_string.capacity() >= 3);
904 }
905
906 #[test]
907 fn test_os_string_reserve() {
908 let mut os_string = OsString::new();
909 assert_eq!(os_string.capacity(), 0);
910
911 os_string.reserve(2);
912 assert!(os_string.capacity() >= 2);
913
914 for _ in 0..16 {
915 os_string.push("a");
916 }
917
918 assert!(os_string.capacity() >= 16);
919 os_string.reserve(16);
920 assert!(os_string.capacity() >= 32);
921
922 os_string.push("a");
923
924 os_string.reserve(16);
925 assert!(os_string.capacity() >= 33)
926 }
927
928 #[test]
929 fn test_os_string_reserve_exact() {
930 let mut os_string = OsString::new();
931 assert_eq!(os_string.capacity(), 0);
932
933 os_string.reserve_exact(2);
934 assert!(os_string.capacity() >= 2);
935
936 for _ in 0..16 {
937 os_string.push("a");
938 }
939
940 assert!(os_string.capacity() >= 16);
941 os_string.reserve_exact(16);
942 assert!(os_string.capacity() >= 32);
943
944 os_string.push("a");
945
946 os_string.reserve_exact(16);
947 assert!(os_string.capacity() >= 33)
948 }
949
54a0048b
SL
950 #[test]
951 fn test_os_string_default() {
952 let os_string: OsString = Default::default();
953 assert_eq!("", &os_string);
954 }
955
7453a54e
SL
956 #[test]
957 fn test_os_str_is_empty() {
958 let mut os_string = OsString::new();
959 assert!(os_string.is_empty());
960
961 os_string.push("abc");
962 assert!(!os_string.is_empty());
963
964 os_string.clear();
965 assert!(os_string.is_empty());
966 }
967
968 #[test]
969 fn test_os_str_len() {
970 let mut os_string = OsString::new();
971 assert_eq!(0, os_string.len());
972
973 os_string.push("abc");
974 assert_eq!(3, os_string.len());
975
976 os_string.clear();
977 assert_eq!(0, os_string.len());
978 }
54a0048b
SL
979
980 #[test]
981 fn test_os_str_default() {
982 let os_str: &OsStr = Default::default();
983 assert_eq!("", os_str);
984 }
8bb4bdeb
XL
985
986 #[test]
987 fn into_boxed() {
988 let orig = "Hello, world!";
989 let os_str = OsStr::new(orig);
cc61c64b
XL
990 let boxed: Box<OsStr> = Box::from(os_str);
991 let os_string = os_str.to_owned().into_boxed_os_str().into_os_string();
992 assert_eq!(os_str, &*boxed);
993 assert_eq!(&*boxed, &*os_string);
994 assert_eq!(&*os_string, os_str);
8bb4bdeb
XL
995 }
996
997 #[test]
998 fn boxed_default() {
999 let boxed = <Box<OsStr>>::default();
1000 assert!(boxed.is_empty());
1001 }
cc61c64b
XL
1002
1003 #[test]
1004 fn test_os_str_clone_into() {
1005 let mut os_string = OsString::with_capacity(123);
1006 os_string.push("hello");
1007 let os_str = OsStr::new("bonjour");
1008 os_str.clone_into(&mut os_string);
1009 assert_eq!(os_str, os_string);
1010 assert!(os_string.capacity() >= 123);
1011 }
ff7c6d11
XL
1012
1013 #[test]
1014 fn into_rc() {
1015 let orig = "Hello, world!";
1016 let os_str = OsStr::new(orig);
1017 let rc: Rc<OsStr> = Rc::from(os_str);
1018 let arc: Arc<OsStr> = Arc::from(os_str);
1019
1020 assert_eq!(&*rc, os_str);
1021 assert_eq!(&*arc, os_str);
1022
1023 let rc2: Rc<OsStr> = Rc::from(os_str.to_owned());
1024 let arc2: Arc<OsStr> = Arc::from(os_str.to_owned());
1025
1026 assert_eq!(&*rc2, os_str);
1027 assert_eq!(&*arc2, os_str);
1028 }
7453a54e 1029}