embedded_ffi/
os_str.rs

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