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