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