1 | //! The [`OsStr`] and [`OsString`] types and associated utilities. |
2 | |
3 | #[cfg (test)] |
4 | mod tests; |
5 | |
6 | use crate::borrow::{Borrow, Cow}; |
7 | use crate::cmp; |
8 | use crate::collections::TryReserveError; |
9 | use crate::fmt; |
10 | use crate::hash::{Hash, Hasher}; |
11 | use crate::ops::{self, Range}; |
12 | use crate::rc::Rc; |
13 | use crate::slice; |
14 | use crate::str::FromStr; |
15 | use crate::sync::Arc; |
16 | |
17 | use crate::sys::os_str::{Buf, Slice}; |
18 | use crate::sys_common::{AsInner, FromInner, IntoInner}; |
19 | |
20 | /// A type that can represent owned, mutable platform-native strings, but is |
21 | /// cheaply inter-convertible with Rust strings. |
22 | /// |
23 | /// The need for this type arises from the fact that: |
24 | /// |
25 | /// * On Unix systems, strings are often arbitrary sequences of non-zero |
26 | /// bytes, in many cases interpreted as UTF-8. |
27 | /// |
28 | /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit |
29 | /// values, interpreted as UTF-16 when it is valid to do so. |
30 | /// |
31 | /// * In Rust, strings are always valid UTF-8, which may contain zeros. |
32 | /// |
33 | /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust |
34 | /// and platform-native string values, and in particular allowing a Rust string |
35 | /// to be converted into an "OS" string with no cost if possible. A consequence |
36 | /// of this is that `OsString` instances are *not* `NUL` terminated; in order |
37 | /// to pass to e.g., Unix system call, you should create a [`CStr`]. |
38 | /// |
39 | /// `OsString` is to <code>&[OsStr]</code> as [`String`] is to <code>&[str]</code>: the former |
40 | /// in each pair are owned strings; the latter are borrowed |
41 | /// references. |
42 | /// |
43 | /// Note, `OsString` and [`OsStr`] internally do not necessarily hold strings in |
44 | /// the form native to the platform; While on Unix, strings are stored as a |
45 | /// sequence of 8-bit values, on Windows, where strings are 16-bit value based |
46 | /// as just discussed, strings are also actually stored as a sequence of 8-bit |
47 | /// values, encoded in a less-strict variant of UTF-8. This is useful to |
48 | /// understand when handling capacity and length values. |
49 | /// |
50 | /// # Capacity of `OsString` |
51 | /// |
52 | /// Capacity uses units of UTF-8 bytes for OS strings which were created from valid unicode, and |
53 | /// uses units of bytes in an unspecified encoding for other contents. On a given target, all |
54 | /// `OsString` and `OsStr` values use the same units for capacity, so the following will work: |
55 | /// ``` |
56 | /// use std::ffi::{OsStr, OsString}; |
57 | /// |
58 | /// fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString { |
59 | /// let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate |
60 | /// ret.push(a); // This will not allocate further |
61 | /// ret.push(b); // This will not allocate further |
62 | /// ret |
63 | /// } |
64 | /// ``` |
65 | /// |
66 | /// # Creating an `OsString` |
67 | /// |
68 | /// **From a Rust string**: `OsString` implements |
69 | /// <code>[From]<[String]></code>, so you can use <code>my_string.[into]\()</code> to |
70 | /// create an `OsString` from a normal Rust string. |
71 | /// |
72 | /// **From slices:** Just like you can start with an empty Rust |
73 | /// [`String`] and then [`String::push_str`] some <code>&[str]</code> |
74 | /// sub-string slices into it, you can create an empty `OsString` with |
75 | /// the [`OsString::new`] method and then push string slices into it with the |
76 | /// [`OsString::push`] method. |
77 | /// |
78 | /// # Extracting a borrowed reference to the whole OS string |
79 | /// |
80 | /// You can use the [`OsString::as_os_str`] method to get an <code>&[OsStr]</code> from |
81 | /// an `OsString`; this is effectively a borrowed reference to the |
82 | /// whole string. |
83 | /// |
84 | /// # Conversions |
85 | /// |
86 | /// See the [module's toplevel documentation about conversions][conversions] for a discussion on |
87 | /// the traits which `OsString` implements for [conversions] from/to native representations. |
88 | /// |
89 | /// [`CStr`]: crate::ffi::CStr |
90 | /// [conversions]: super#conversions |
91 | /// [into]: Into::into |
92 | #[cfg_attr (not(test), rustc_diagnostic_item = "OsString" )] |
93 | #[stable (feature = "rust1" , since = "1.0.0" )] |
94 | pub struct OsString { |
95 | inner: Buf, |
96 | } |
97 | |
98 | /// Allows extension traits within `std`. |
99 | #[unstable (feature = "sealed" , issue = "none" )] |
100 | impl crate::sealed::Sealed for OsString {} |
101 | |
102 | /// Borrowed reference to an OS string (see [`OsString`]). |
103 | /// |
104 | /// This type represents a borrowed reference to a string in the operating system's preferred |
105 | /// representation. |
106 | /// |
107 | /// `&OsStr` is to [`OsString`] as <code>&[str]</code> is to [`String`]: the |
108 | /// former in each pair are borrowed references; the latter are owned strings. |
109 | /// |
110 | /// See the [module's toplevel documentation about conversions][conversions] for a discussion on |
111 | /// the traits which `OsStr` implements for [conversions] from/to native representations. |
112 | /// |
113 | /// [conversions]: super#conversions |
114 | #[cfg_attr (not(test), rustc_diagnostic_item = "OsStr" )] |
115 | #[stable (feature = "rust1" , since = "1.0.0" )] |
116 | // `OsStr::from_inner` current implementation relies |
117 | // on `OsStr` being layout-compatible with `Slice`. |
118 | // However, `OsStr` layout is considered an implementation detail and must not be relied upon. We |
119 | // want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under |
120 | // `cfg(doc)`. This is an ad-hoc implementation of attribute privacy. |
121 | #[cfg_attr (not(doc), repr(transparent))] |
122 | pub struct OsStr { |
123 | inner: Slice, |
124 | } |
125 | |
126 | /// Allows extension traits within `std`. |
127 | #[unstable (feature = "sealed" , issue = "none" )] |
128 | impl crate::sealed::Sealed for OsStr {} |
129 | |
130 | impl OsString { |
131 | /// Constructs a new empty `OsString`. |
132 | /// |
133 | /// # Examples |
134 | /// |
135 | /// ``` |
136 | /// use std::ffi::OsString; |
137 | /// |
138 | /// let os_string = OsString::new(); |
139 | /// ``` |
140 | #[stable (feature = "rust1" , since = "1.0.0" )] |
141 | #[must_use ] |
142 | #[inline ] |
143 | pub fn new() -> OsString { |
144 | OsString { inner: Buf::from_string(String::new()) } |
145 | } |
146 | |
147 | /// Converts bytes to an `OsString` without checking that the bytes contains |
148 | /// valid [`OsStr`]-encoded data. |
149 | /// |
150 | /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8. |
151 | /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit |
152 | /// ASCII. |
153 | /// |
154 | /// See the [module's toplevel documentation about conversions][conversions] for safe, |
155 | /// cross-platform [conversions] from/to native representations. |
156 | /// |
157 | /// # Safety |
158 | /// |
159 | /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of |
160 | /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version |
161 | /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent |
162 | /// over the network or stored in a file will likely violate these safety rules. |
163 | /// |
164 | /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be |
165 | /// split either immediately before or immediately after any valid non-empty UTF-8 substring. |
166 | /// |
167 | /// # Example |
168 | /// |
169 | /// ``` |
170 | /// use std::ffi::OsStr; |
171 | /// |
172 | /// let os_str = OsStr::new("Mary had a little lamb" ); |
173 | /// let bytes = os_str.as_encoded_bytes(); |
174 | /// let words = bytes.split(|b| *b == b' ' ); |
175 | /// let words: Vec<&OsStr> = words.map(|word| { |
176 | /// // SAFETY: |
177 | /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes` |
178 | /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring |
179 | /// unsafe { OsStr::from_encoded_bytes_unchecked(word) } |
180 | /// }).collect(); |
181 | /// ``` |
182 | /// |
183 | /// [conversions]: super#conversions |
184 | #[inline ] |
185 | #[stable (feature = "os_str_bytes" , since = "1.74.0" )] |
186 | pub unsafe fn from_encoded_bytes_unchecked(bytes: Vec<u8>) -> Self { |
187 | OsString { inner: Buf::from_encoded_bytes_unchecked(bytes) } |
188 | } |
189 | |
190 | /// Converts to an [`OsStr`] slice. |
191 | /// |
192 | /// # Examples |
193 | /// |
194 | /// ``` |
195 | /// use std::ffi::{OsString, OsStr}; |
196 | /// |
197 | /// let os_string = OsString::from("foo" ); |
198 | /// let os_str = OsStr::new("foo" ); |
199 | /// assert_eq!(os_string.as_os_str(), os_str); |
200 | /// ``` |
201 | #[stable (feature = "rust1" , since = "1.0.0" )] |
202 | #[must_use ] |
203 | #[inline ] |
204 | pub fn as_os_str(&self) -> &OsStr { |
205 | self |
206 | } |
207 | |
208 | /// Converts the `OsString` into a byte slice. To convert the byte slice back into an |
209 | /// `OsString`, use the [`OsStr::from_encoded_bytes_unchecked`] function. |
210 | /// |
211 | /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8. |
212 | /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit |
213 | /// ASCII. |
214 | /// |
215 | /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should |
216 | /// be treated as opaque and only comparable within the same Rust version built for the same |
217 | /// target platform. For example, sending the bytes over the network or storing it in a file |
218 | /// will likely result in incompatible data. See [`OsString`] for more encoding details |
219 | /// and [`std::ffi`] for platform-specific, specified conversions. |
220 | /// |
221 | /// [`std::ffi`]: crate::ffi |
222 | #[inline ] |
223 | #[stable (feature = "os_str_bytes" , since = "1.74.0" )] |
224 | pub fn into_encoded_bytes(self) -> Vec<u8> { |
225 | self.inner.into_encoded_bytes() |
226 | } |
227 | |
228 | /// Converts the `OsString` into a [`String`] if it contains valid Unicode data. |
229 | /// |
230 | /// On failure, ownership of the original `OsString` is returned. |
231 | /// |
232 | /// # Examples |
233 | /// |
234 | /// ``` |
235 | /// use std::ffi::OsString; |
236 | /// |
237 | /// let os_string = OsString::from("foo" ); |
238 | /// let string = os_string.into_string(); |
239 | /// assert_eq!(string, Ok(String::from("foo" ))); |
240 | /// ``` |
241 | #[stable (feature = "rust1" , since = "1.0.0" )] |
242 | #[inline ] |
243 | pub fn into_string(self) -> Result<String, OsString> { |
244 | self.inner.into_string().map_err(|buf| OsString { inner: buf }) |
245 | } |
246 | |
247 | /// Extends the string with the given <code>&[OsStr]</code> slice. |
248 | /// |
249 | /// # Examples |
250 | /// |
251 | /// ``` |
252 | /// use std::ffi::OsString; |
253 | /// |
254 | /// let mut os_string = OsString::from("foo" ); |
255 | /// os_string.push("bar" ); |
256 | /// assert_eq!(&os_string, "foobar" ); |
257 | /// ``` |
258 | #[stable (feature = "rust1" , since = "1.0.0" )] |
259 | #[inline ] |
260 | #[rustc_confusables ("append" , "put" )] |
261 | pub fn push<T: AsRef<OsStr>>(&mut self, s: T) { |
262 | self.inner.push_slice(&s.as_ref().inner) |
263 | } |
264 | |
265 | /// Creates a new `OsString` with at least the given capacity. |
266 | /// |
267 | /// The string will be able to hold at least `capacity` length units of other |
268 | /// OS strings without reallocating. This method is allowed to allocate for |
269 | /// more units than `capacity`. If `capacity` is 0, the string will not |
270 | /// allocate. |
271 | /// |
272 | /// See the main `OsString` documentation information about encoding and capacity units. |
273 | /// |
274 | /// # Examples |
275 | /// |
276 | /// ``` |
277 | /// use std::ffi::OsString; |
278 | /// |
279 | /// let mut os_string = OsString::with_capacity(10); |
280 | /// let capacity = os_string.capacity(); |
281 | /// |
282 | /// // This push is done without reallocating |
283 | /// os_string.push("foo" ); |
284 | /// |
285 | /// assert_eq!(capacity, os_string.capacity()); |
286 | /// ``` |
287 | #[stable (feature = "osstring_simple_functions" , since = "1.9.0" )] |
288 | #[must_use ] |
289 | #[inline ] |
290 | pub fn with_capacity(capacity: usize) -> OsString { |
291 | OsString { inner: Buf::with_capacity(capacity) } |
292 | } |
293 | |
294 | /// Truncates the `OsString` to zero length. |
295 | /// |
296 | /// # Examples |
297 | /// |
298 | /// ``` |
299 | /// use std::ffi::OsString; |
300 | /// |
301 | /// let mut os_string = OsString::from("foo" ); |
302 | /// assert_eq!(&os_string, "foo" ); |
303 | /// |
304 | /// os_string.clear(); |
305 | /// assert_eq!(&os_string, "" ); |
306 | /// ``` |
307 | #[stable (feature = "osstring_simple_functions" , since = "1.9.0" )] |
308 | #[inline ] |
309 | pub fn clear(&mut self) { |
310 | self.inner.clear() |
311 | } |
312 | |
313 | /// Returns the capacity this `OsString` can hold without reallocating. |
314 | /// |
315 | /// See the main `OsString` documentation information about encoding and capacity units. |
316 | /// |
317 | /// # Examples |
318 | /// |
319 | /// ``` |
320 | /// use std::ffi::OsString; |
321 | /// |
322 | /// let os_string = OsString::with_capacity(10); |
323 | /// assert!(os_string.capacity() >= 10); |
324 | /// ``` |
325 | #[stable (feature = "osstring_simple_functions" , since = "1.9.0" )] |
326 | #[must_use ] |
327 | #[inline ] |
328 | pub fn capacity(&self) -> usize { |
329 | self.inner.capacity() |
330 | } |
331 | |
332 | /// Reserves capacity for at least `additional` more capacity to be inserted |
333 | /// in the given `OsString`. Does nothing if the capacity is |
334 | /// already sufficient. |
335 | /// |
336 | /// The collection may reserve more space to speculatively avoid frequent reallocations. |
337 | /// |
338 | /// See the main `OsString` documentation information about encoding and capacity units. |
339 | /// |
340 | /// # Examples |
341 | /// |
342 | /// ``` |
343 | /// use std::ffi::OsString; |
344 | /// |
345 | /// let mut s = OsString::new(); |
346 | /// s.reserve(10); |
347 | /// assert!(s.capacity() >= 10); |
348 | /// ``` |
349 | #[stable (feature = "osstring_simple_functions" , since = "1.9.0" )] |
350 | #[inline ] |
351 | pub fn reserve(&mut self, additional: usize) { |
352 | self.inner.reserve(additional) |
353 | } |
354 | |
355 | /// Tries to reserve capacity for at least `additional` more length units |
356 | /// in the given `OsString`. The string may reserve more space to speculatively avoid |
357 | /// frequent reallocations. After calling `try_reserve`, capacity will be |
358 | /// greater than or equal to `self.len() + additional` if it returns `Ok(())`. |
359 | /// Does nothing if capacity is already sufficient. This method preserves |
360 | /// the contents even if an error occurs. |
361 | /// |
362 | /// See the main `OsString` documentation information about encoding and capacity units. |
363 | /// |
364 | /// # Errors |
365 | /// |
366 | /// If the capacity overflows, or the allocator reports a failure, then an error |
367 | /// is returned. |
368 | /// |
369 | /// # Examples |
370 | /// |
371 | /// ``` |
372 | /// use std::ffi::{OsStr, OsString}; |
373 | /// use std::collections::TryReserveError; |
374 | /// |
375 | /// fn process_data(data: &str) -> Result<OsString, TryReserveError> { |
376 | /// let mut s = OsString::new(); |
377 | /// |
378 | /// // Pre-reserve the memory, exiting if we can't |
379 | /// s.try_reserve(OsStr::new(data).len())?; |
380 | /// |
381 | /// // Now we know this can't OOM in the middle of our complex work |
382 | /// s.push(data); |
383 | /// |
384 | /// Ok(s) |
385 | /// } |
386 | /// # process_data("123" ).expect("why is the test harness OOMing on 3 bytes?" ); |
387 | /// ``` |
388 | #[stable (feature = "try_reserve_2" , since = "1.63.0" )] |
389 | #[inline ] |
390 | pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { |
391 | self.inner.try_reserve(additional) |
392 | } |
393 | |
394 | /// Reserves the minimum capacity for at least `additional` more capacity to |
395 | /// be inserted in the given `OsString`. Does nothing if the capacity is |
396 | /// already sufficient. |
397 | /// |
398 | /// Note that the allocator may give the collection more space than it |
399 | /// requests. Therefore, capacity can not be relied upon to be precisely |
400 | /// minimal. Prefer [`reserve`] if future insertions are expected. |
401 | /// |
402 | /// [`reserve`]: OsString::reserve |
403 | /// |
404 | /// See the main `OsString` documentation information about encoding and capacity units. |
405 | /// |
406 | /// # Examples |
407 | /// |
408 | /// ``` |
409 | /// use std::ffi::OsString; |
410 | /// |
411 | /// let mut s = OsString::new(); |
412 | /// s.reserve_exact(10); |
413 | /// assert!(s.capacity() >= 10); |
414 | /// ``` |
415 | #[stable (feature = "osstring_simple_functions" , since = "1.9.0" )] |
416 | #[inline ] |
417 | pub fn reserve_exact(&mut self, additional: usize) { |
418 | self.inner.reserve_exact(additional) |
419 | } |
420 | |
421 | /// Tries to reserve the minimum capacity for at least `additional` |
422 | /// more length units in the given `OsString`. After calling |
423 | /// `try_reserve_exact`, capacity will be greater than or equal to |
424 | /// `self.len() + additional` if it returns `Ok(())`. |
425 | /// Does nothing if the capacity is already sufficient. |
426 | /// |
427 | /// Note that the allocator may give the `OsString` more space than it |
428 | /// requests. Therefore, capacity can not be relied upon to be precisely |
429 | /// minimal. Prefer [`try_reserve`] if future insertions are expected. |
430 | /// |
431 | /// [`try_reserve`]: OsString::try_reserve |
432 | /// |
433 | /// See the main `OsString` documentation information about encoding and capacity units. |
434 | /// |
435 | /// # Errors |
436 | /// |
437 | /// If the capacity overflows, or the allocator reports a failure, then an error |
438 | /// is returned. |
439 | /// |
440 | /// # Examples |
441 | /// |
442 | /// ``` |
443 | /// use std::ffi::{OsStr, OsString}; |
444 | /// use std::collections::TryReserveError; |
445 | /// |
446 | /// fn process_data(data: &str) -> Result<OsString, TryReserveError> { |
447 | /// let mut s = OsString::new(); |
448 | /// |
449 | /// // Pre-reserve the memory, exiting if we can't |
450 | /// s.try_reserve_exact(OsStr::new(data).len())?; |
451 | /// |
452 | /// // Now we know this can't OOM in the middle of our complex work |
453 | /// s.push(data); |
454 | /// |
455 | /// Ok(s) |
456 | /// } |
457 | /// # process_data("123" ).expect("why is the test harness OOMing on 3 bytes?" ); |
458 | /// ``` |
459 | #[stable (feature = "try_reserve_2" , since = "1.63.0" )] |
460 | #[inline ] |
461 | pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { |
462 | self.inner.try_reserve_exact(additional) |
463 | } |
464 | |
465 | /// Shrinks the capacity of the `OsString` to match its length. |
466 | /// |
467 | /// See the main `OsString` documentation information about encoding and capacity units. |
468 | /// |
469 | /// # Examples |
470 | /// |
471 | /// ``` |
472 | /// use std::ffi::OsString; |
473 | /// |
474 | /// let mut s = OsString::from("foo" ); |
475 | /// |
476 | /// s.reserve(100); |
477 | /// assert!(s.capacity() >= 100); |
478 | /// |
479 | /// s.shrink_to_fit(); |
480 | /// assert_eq!(3, s.capacity()); |
481 | /// ``` |
482 | #[stable (feature = "osstring_shrink_to_fit" , since = "1.19.0" )] |
483 | #[inline ] |
484 | pub fn shrink_to_fit(&mut self) { |
485 | self.inner.shrink_to_fit() |
486 | } |
487 | |
488 | /// Shrinks the capacity of the `OsString` with a lower bound. |
489 | /// |
490 | /// The capacity will remain at least as large as both the length |
491 | /// and the supplied value. |
492 | /// |
493 | /// If the current capacity is less than the lower limit, this is a no-op. |
494 | /// |
495 | /// See the main `OsString` documentation information about encoding and capacity units. |
496 | /// |
497 | /// # Examples |
498 | /// |
499 | /// ``` |
500 | /// use std::ffi::OsString; |
501 | /// |
502 | /// let mut s = OsString::from("foo" ); |
503 | /// |
504 | /// s.reserve(100); |
505 | /// assert!(s.capacity() >= 100); |
506 | /// |
507 | /// s.shrink_to(10); |
508 | /// assert!(s.capacity() >= 10); |
509 | /// s.shrink_to(0); |
510 | /// assert!(s.capacity() >= 3); |
511 | /// ``` |
512 | #[inline ] |
513 | #[stable (feature = "shrink_to" , since = "1.56.0" )] |
514 | pub fn shrink_to(&mut self, min_capacity: usize) { |
515 | self.inner.shrink_to(min_capacity) |
516 | } |
517 | |
518 | /// Converts this `OsString` into a boxed [`OsStr`]. |
519 | /// |
520 | /// # Examples |
521 | /// |
522 | /// ``` |
523 | /// use std::ffi::{OsString, OsStr}; |
524 | /// |
525 | /// let s = OsString::from("hello" ); |
526 | /// |
527 | /// let b: Box<OsStr> = s.into_boxed_os_str(); |
528 | /// ``` |
529 | #[must_use = "`self` will be dropped if the result is not used" ] |
530 | #[stable (feature = "into_boxed_os_str" , since = "1.20.0" )] |
531 | pub fn into_boxed_os_str(self) -> Box<OsStr> { |
532 | let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr; |
533 | unsafe { Box::from_raw(rw) } |
534 | } |
535 | } |
536 | |
537 | #[stable (feature = "rust1" , since = "1.0.0" )] |
538 | impl From<String> for OsString { |
539 | /// Converts a [`String`] into an [`OsString`]. |
540 | /// |
541 | /// This conversion does not allocate or copy memory. |
542 | #[inline ] |
543 | fn from(s: String) -> OsString { |
544 | OsString { inner: Buf::from_string(s) } |
545 | } |
546 | } |
547 | |
548 | #[stable (feature = "rust1" , since = "1.0.0" )] |
549 | impl<T: ?Sized + AsRef<OsStr>> From<&T> for OsString { |
550 | /// Copies any value implementing <code>[AsRef]<[OsStr]></code> |
551 | /// into a newly allocated [`OsString`]. |
552 | fn from(s: &T) -> OsString { |
553 | s.as_ref().to_os_string() |
554 | } |
555 | } |
556 | |
557 | #[stable (feature = "rust1" , since = "1.0.0" )] |
558 | impl ops::Index<ops::RangeFull> for OsString { |
559 | type Output = OsStr; |
560 | |
561 | #[inline ] |
562 | fn index(&self, _index: ops::RangeFull) -> &OsStr { |
563 | OsStr::from_inner(self.inner.as_slice()) |
564 | } |
565 | } |
566 | |
567 | #[stable (feature = "mut_osstr" , since = "1.44.0" )] |
568 | impl ops::IndexMut<ops::RangeFull> for OsString { |
569 | #[inline ] |
570 | fn index_mut(&mut self, _index: ops::RangeFull) -> &mut OsStr { |
571 | OsStr::from_inner_mut(self.inner.as_mut_slice()) |
572 | } |
573 | } |
574 | |
575 | #[stable (feature = "rust1" , since = "1.0.0" )] |
576 | impl ops::Deref for OsString { |
577 | type Target = OsStr; |
578 | |
579 | #[inline ] |
580 | fn deref(&self) -> &OsStr { |
581 | &self[..] |
582 | } |
583 | } |
584 | |
585 | #[stable (feature = "mut_osstr" , since = "1.44.0" )] |
586 | impl ops::DerefMut for OsString { |
587 | #[inline ] |
588 | fn deref_mut(&mut self) -> &mut OsStr { |
589 | &mut self[..] |
590 | } |
591 | } |
592 | |
593 | #[stable (feature = "osstring_default" , since = "1.9.0" )] |
594 | impl Default for OsString { |
595 | /// Constructs an empty `OsString`. |
596 | #[inline ] |
597 | fn default() -> OsString { |
598 | OsString::new() |
599 | } |
600 | } |
601 | |
602 | #[stable (feature = "rust1" , since = "1.0.0" )] |
603 | impl Clone for OsString { |
604 | #[inline ] |
605 | fn clone(&self) -> Self { |
606 | OsString { inner: self.inner.clone() } |
607 | } |
608 | |
609 | /// Clones the contents of `source` into `self`. |
610 | /// |
611 | /// This method is preferred over simply assigning `source.clone()` to `self`, |
612 | /// as it avoids reallocation if possible. |
613 | #[inline ] |
614 | fn clone_from(&mut self, source: &Self) { |
615 | self.inner.clone_from(&source.inner) |
616 | } |
617 | } |
618 | |
619 | #[stable (feature = "rust1" , since = "1.0.0" )] |
620 | impl fmt::Debug for OsString { |
621 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
622 | fmt::Debug::fmt(&**self, f:formatter) |
623 | } |
624 | } |
625 | |
626 | #[stable (feature = "rust1" , since = "1.0.0" )] |
627 | impl PartialEq for OsString { |
628 | #[inline ] |
629 | fn eq(&self, other: &OsString) -> bool { |
630 | &**self == &**other |
631 | } |
632 | } |
633 | |
634 | #[stable (feature = "rust1" , since = "1.0.0" )] |
635 | impl PartialEq<str> for OsString { |
636 | #[inline ] |
637 | fn eq(&self, other: &str) -> bool { |
638 | &**self == other |
639 | } |
640 | } |
641 | |
642 | #[stable (feature = "rust1" , since = "1.0.0" )] |
643 | impl PartialEq<OsString> for str { |
644 | #[inline ] |
645 | fn eq(&self, other: &OsString) -> bool { |
646 | &**other == self |
647 | } |
648 | } |
649 | |
650 | #[stable (feature = "os_str_str_ref_eq" , since = "1.29.0" )] |
651 | impl PartialEq<&str> for OsString { |
652 | #[inline ] |
653 | fn eq(&self, other: &&str) -> bool { |
654 | **self == **other |
655 | } |
656 | } |
657 | |
658 | #[stable (feature = "os_str_str_ref_eq" , since = "1.29.0" )] |
659 | impl<'a> PartialEq<OsString> for &'a str { |
660 | #[inline ] |
661 | fn eq(&self, other: &OsString) -> bool { |
662 | **other == **self |
663 | } |
664 | } |
665 | |
666 | #[stable (feature = "rust1" , since = "1.0.0" )] |
667 | impl Eq for OsString {} |
668 | |
669 | #[stable (feature = "rust1" , since = "1.0.0" )] |
670 | impl PartialOrd for OsString { |
671 | #[inline ] |
672 | fn partial_cmp(&self, other: &OsString) -> Option<cmp::Ordering> { |
673 | (&**self).partial_cmp(&**other) |
674 | } |
675 | #[inline ] |
676 | fn lt(&self, other: &OsString) -> bool { |
677 | &**self < &**other |
678 | } |
679 | #[inline ] |
680 | fn le(&self, other: &OsString) -> bool { |
681 | &**self <= &**other |
682 | } |
683 | #[inline ] |
684 | fn gt(&self, other: &OsString) -> bool { |
685 | &**self > &**other |
686 | } |
687 | #[inline ] |
688 | fn ge(&self, other: &OsString) -> bool { |
689 | &**self >= &**other |
690 | } |
691 | } |
692 | |
693 | #[stable (feature = "rust1" , since = "1.0.0" )] |
694 | impl PartialOrd<str> for OsString { |
695 | #[inline ] |
696 | fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> { |
697 | (&**self).partial_cmp(other) |
698 | } |
699 | } |
700 | |
701 | #[stable (feature = "rust1" , since = "1.0.0" )] |
702 | impl Ord for OsString { |
703 | #[inline ] |
704 | fn cmp(&self, other: &OsString) -> cmp::Ordering { |
705 | (&**self).cmp(&**other) |
706 | } |
707 | } |
708 | |
709 | #[stable (feature = "rust1" , since = "1.0.0" )] |
710 | impl Hash for OsString { |
711 | #[inline ] |
712 | fn hash<H: Hasher>(&self, state: &mut H) { |
713 | (&**self).hash(state) |
714 | } |
715 | } |
716 | |
717 | #[stable (feature = "os_string_fmt_write" , since = "1.64.0" )] |
718 | impl fmt::Write for OsString { |
719 | fn write_str(&mut self, s: &str) -> fmt::Result { |
720 | self.push(s); |
721 | Ok(()) |
722 | } |
723 | } |
724 | |
725 | impl OsStr { |
726 | /// Coerces into an `OsStr` slice. |
727 | /// |
728 | /// # Examples |
729 | /// |
730 | /// ``` |
731 | /// use std::ffi::OsStr; |
732 | /// |
733 | /// let os_str = OsStr::new("foo" ); |
734 | /// ``` |
735 | #[inline ] |
736 | #[stable (feature = "rust1" , since = "1.0.0" )] |
737 | pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr { |
738 | s.as_ref() |
739 | } |
740 | |
741 | /// Converts a slice of bytes to an OS string slice without checking that the string contains |
742 | /// valid `OsStr`-encoded data. |
743 | /// |
744 | /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8. |
745 | /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit |
746 | /// ASCII. |
747 | /// |
748 | /// See the [module's toplevel documentation about conversions][conversions] for safe, |
749 | /// cross-platform [conversions] from/to native representations. |
750 | /// |
751 | /// # Safety |
752 | /// |
753 | /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of |
754 | /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version |
755 | /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent |
756 | /// over the network or stored in a file will likely violate these safety rules. |
757 | /// |
758 | /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_encoded_bytes`] can be |
759 | /// split either immediately before or immediately after any valid non-empty UTF-8 substring. |
760 | /// |
761 | /// # Example |
762 | /// |
763 | /// ``` |
764 | /// use std::ffi::OsStr; |
765 | /// |
766 | /// let os_str = OsStr::new("Mary had a little lamb" ); |
767 | /// let bytes = os_str.as_encoded_bytes(); |
768 | /// let words = bytes.split(|b| *b == b' ' ); |
769 | /// let words: Vec<&OsStr> = words.map(|word| { |
770 | /// // SAFETY: |
771 | /// // - Each `word` only contains content that originated from `OsStr::as_encoded_bytes` |
772 | /// // - Only split with ASCII whitespace which is a non-empty UTF-8 substring |
773 | /// unsafe { OsStr::from_encoded_bytes_unchecked(word) } |
774 | /// }).collect(); |
775 | /// ``` |
776 | /// |
777 | /// [conversions]: super#conversions |
778 | #[inline ] |
779 | #[stable (feature = "os_str_bytes" , since = "1.74.0" )] |
780 | pub unsafe fn from_encoded_bytes_unchecked(bytes: &[u8]) -> &Self { |
781 | Self::from_inner(Slice::from_encoded_bytes_unchecked(bytes)) |
782 | } |
783 | |
784 | #[inline ] |
785 | fn from_inner(inner: &Slice) -> &OsStr { |
786 | // SAFETY: OsStr is just a wrapper of Slice, |
787 | // therefore converting &Slice to &OsStr is safe. |
788 | unsafe { &*(inner as *const Slice as *const OsStr) } |
789 | } |
790 | |
791 | #[inline ] |
792 | fn from_inner_mut(inner: &mut Slice) -> &mut OsStr { |
793 | // SAFETY: OsStr is just a wrapper of Slice, |
794 | // therefore converting &mut Slice to &mut OsStr is safe. |
795 | // Any method that mutates OsStr must be careful not to |
796 | // break platform-specific encoding, in particular Wtf8 on Windows. |
797 | unsafe { &mut *(inner as *mut Slice as *mut OsStr) } |
798 | } |
799 | |
800 | /// Yields a <code>&[str]</code> slice if the `OsStr` is valid Unicode. |
801 | /// |
802 | /// This conversion may entail doing a check for UTF-8 validity. |
803 | /// |
804 | /// # Examples |
805 | /// |
806 | /// ``` |
807 | /// use std::ffi::OsStr; |
808 | /// |
809 | /// let os_str = OsStr::new("foo" ); |
810 | /// assert_eq!(os_str.to_str(), Some("foo" )); |
811 | /// ``` |
812 | #[stable (feature = "rust1" , since = "1.0.0" )] |
813 | #[must_use = "this returns the result of the operation, \ |
814 | without modifying the original" ] |
815 | #[inline ] |
816 | pub fn to_str(&self) -> Option<&str> { |
817 | self.inner.to_str().ok() |
818 | } |
819 | |
820 | /// Converts an `OsStr` to a <code>[Cow]<[str]></code>. |
821 | /// |
822 | /// Any non-Unicode sequences are replaced with |
823 | /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]. |
824 | /// |
825 | /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER |
826 | /// |
827 | /// # Examples |
828 | /// |
829 | /// Calling `to_string_lossy` on an `OsStr` with invalid unicode: |
830 | /// |
831 | /// ``` |
832 | /// // Note, due to differences in how Unix and Windows represent strings, |
833 | /// // we are forced to complicate this example, setting up example `OsStr`s |
834 | /// // with different source data and via different platform extensions. |
835 | /// // Understand that in reality you could end up with such example invalid |
836 | /// // sequences simply through collecting user command line arguments, for |
837 | /// // example. |
838 | /// |
839 | /// #[cfg(unix)] { |
840 | /// use std::ffi::OsStr; |
841 | /// use std::os::unix::ffi::OsStrExt; |
842 | /// |
843 | /// // Here, the values 0x66 and 0x6f correspond to 'f' and 'o' |
844 | /// // respectively. The value 0x80 is a lone continuation byte, invalid |
845 | /// // in a UTF-8 sequence. |
846 | /// let source = [0x66, 0x6f, 0x80, 0x6f]; |
847 | /// let os_str = OsStr::from_bytes(&source[..]); |
848 | /// |
849 | /// assert_eq!(os_str.to_string_lossy(), "fo�o" ); |
850 | /// } |
851 | /// #[cfg(windows)] { |
852 | /// use std::ffi::OsString; |
853 | /// use std::os::windows::prelude::*; |
854 | /// |
855 | /// // Here the values 0x0066 and 0x006f correspond to 'f' and 'o' |
856 | /// // respectively. The value 0xD800 is a lone surrogate half, invalid |
857 | /// // in a UTF-16 sequence. |
858 | /// let source = [0x0066, 0x006f, 0xD800, 0x006f]; |
859 | /// let os_string = OsString::from_wide(&source[..]); |
860 | /// let os_str = os_string.as_os_str(); |
861 | /// |
862 | /// assert_eq!(os_str.to_string_lossy(), "fo�o" ); |
863 | /// } |
864 | /// ``` |
865 | #[stable (feature = "rust1" , since = "1.0.0" )] |
866 | #[must_use = "this returns the result of the operation, \ |
867 | without modifying the original" ] |
868 | #[inline ] |
869 | pub fn to_string_lossy(&self) -> Cow<'_, str> { |
870 | self.inner.to_string_lossy() |
871 | } |
872 | |
873 | /// Copies the slice into an owned [`OsString`]. |
874 | /// |
875 | /// # Examples |
876 | /// |
877 | /// ``` |
878 | /// use std::ffi::{OsStr, OsString}; |
879 | /// |
880 | /// let os_str = OsStr::new("foo" ); |
881 | /// let os_string = os_str.to_os_string(); |
882 | /// assert_eq!(os_string, OsString::from("foo" )); |
883 | /// ``` |
884 | #[stable (feature = "rust1" , since = "1.0.0" )] |
885 | #[must_use = "this returns the result of the operation, \ |
886 | without modifying the original" ] |
887 | #[inline ] |
888 | pub fn to_os_string(&self) -> OsString { |
889 | OsString { inner: self.inner.to_owned() } |
890 | } |
891 | |
892 | /// Checks whether the `OsStr` is empty. |
893 | /// |
894 | /// # Examples |
895 | /// |
896 | /// ``` |
897 | /// use std::ffi::OsStr; |
898 | /// |
899 | /// let os_str = OsStr::new("" ); |
900 | /// assert!(os_str.is_empty()); |
901 | /// |
902 | /// let os_str = OsStr::new("foo" ); |
903 | /// assert!(!os_str.is_empty()); |
904 | /// ``` |
905 | #[stable (feature = "osstring_simple_functions" , since = "1.9.0" )] |
906 | #[must_use ] |
907 | #[inline ] |
908 | pub fn is_empty(&self) -> bool { |
909 | self.inner.inner.is_empty() |
910 | } |
911 | |
912 | /// Returns the length of this `OsStr`. |
913 | /// |
914 | /// Note that this does **not** return the number of bytes in the string in |
915 | /// OS string form. |
916 | /// |
917 | /// The length returned is that of the underlying storage used by `OsStr`. |
918 | /// As discussed in the [`OsString`] introduction, [`OsString`] and `OsStr` |
919 | /// store strings in a form best suited for cheap inter-conversion between |
920 | /// native-platform and Rust string forms, which may differ significantly |
921 | /// from both of them, including in storage size and encoding. |
922 | /// |
923 | /// This number is simply useful for passing to other methods, like |
924 | /// [`OsString::with_capacity`] to avoid reallocations. |
925 | /// |
926 | /// See the main `OsString` documentation information about encoding and capacity units. |
927 | /// |
928 | /// # Examples |
929 | /// |
930 | /// ``` |
931 | /// use std::ffi::OsStr; |
932 | /// |
933 | /// let os_str = OsStr::new("" ); |
934 | /// assert_eq!(os_str.len(), 0); |
935 | /// |
936 | /// let os_str = OsStr::new("foo" ); |
937 | /// assert_eq!(os_str.len(), 3); |
938 | /// ``` |
939 | #[stable (feature = "osstring_simple_functions" , since = "1.9.0" )] |
940 | #[must_use ] |
941 | #[inline ] |
942 | pub fn len(&self) -> usize { |
943 | self.inner.inner.len() |
944 | } |
945 | |
946 | /// Converts a <code>[Box]<[OsStr]></code> into an [`OsString`] without copying or allocating. |
947 | #[stable (feature = "into_boxed_os_str" , since = "1.20.0" )] |
948 | #[must_use = "`self` will be dropped if the result is not used" ] |
949 | pub fn into_os_string(self: Box<OsStr>) -> OsString { |
950 | let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) }; |
951 | OsString { inner: Buf::from_box(boxed) } |
952 | } |
953 | |
954 | /// Converts an OS string slice to a byte slice. To convert the byte slice back into an OS |
955 | /// string slice, use the [`OsStr::from_encoded_bytes_unchecked`] function. |
956 | /// |
957 | /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8. |
958 | /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit |
959 | /// ASCII. |
960 | /// |
961 | /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should |
962 | /// be treated as opaque and only comparable within the same Rust version built for the same |
963 | /// target platform. For example, sending the slice over the network or storing it in a file |
964 | /// will likely result in incompatible byte slices. See [`OsString`] for more encoding details |
965 | /// and [`std::ffi`] for platform-specific, specified conversions. |
966 | /// |
967 | /// [`std::ffi`]: crate::ffi |
968 | #[inline ] |
969 | #[stable (feature = "os_str_bytes" , since = "1.74.0" )] |
970 | pub fn as_encoded_bytes(&self) -> &[u8] { |
971 | self.inner.as_encoded_bytes() |
972 | } |
973 | |
974 | /// Takes a substring based on a range that corresponds to the return value of |
975 | /// [`OsStr::as_encoded_bytes`]. |
976 | /// |
977 | /// The range's start and end must lie on valid `OsStr` boundaries. |
978 | /// A valid `OsStr` boundary is one of: |
979 | /// - The start of the string |
980 | /// - The end of the string |
981 | /// - Immediately before a valid non-empty UTF-8 substring |
982 | /// - Immediately after a valid non-empty UTF-8 substring |
983 | /// |
984 | /// # Panics |
985 | /// |
986 | /// Panics if `range` does not lie on valid `OsStr` boundaries or if it |
987 | /// exceeds the end of the string. |
988 | /// |
989 | /// # Example |
990 | /// |
991 | /// ``` |
992 | /// #![feature(os_str_slice)] |
993 | /// |
994 | /// use std::ffi::OsStr; |
995 | /// |
996 | /// let os_str = OsStr::new("foo=bar" ); |
997 | /// let bytes = os_str.as_encoded_bytes(); |
998 | /// if let Some(index) = bytes.iter().position(|b| *b == b'=' ) { |
999 | /// let key = os_str.slice_encoded_bytes(..index); |
1000 | /// let value = os_str.slice_encoded_bytes(index + 1..); |
1001 | /// assert_eq!(key, "foo" ); |
1002 | /// assert_eq!(value, "bar" ); |
1003 | /// } |
1004 | /// ``` |
1005 | #[unstable (feature = "os_str_slice" , issue = "118485" )] |
1006 | pub fn slice_encoded_bytes<R: ops::RangeBounds<usize>>(&self, range: R) -> &Self { |
1007 | let encoded_bytes = self.as_encoded_bytes(); |
1008 | let Range { start, end } = slice::range(range, ..encoded_bytes.len()); |
1009 | |
1010 | // `check_public_boundary` should panic if the index does not lie on an |
1011 | // `OsStr` boundary as described above. It's possible to do this in an |
1012 | // encoding-agnostic way, but details of the internal encoding might |
1013 | // permit a more efficient implementation. |
1014 | self.inner.check_public_boundary(start); |
1015 | self.inner.check_public_boundary(end); |
1016 | |
1017 | // SAFETY: `slice::range` ensures that `start` and `end` are valid |
1018 | let slice = unsafe { encoded_bytes.get_unchecked(start..end) }; |
1019 | |
1020 | // SAFETY: `slice` comes from `self` and we validated the boundaries |
1021 | unsafe { Self::from_encoded_bytes_unchecked(slice) } |
1022 | } |
1023 | |
1024 | /// Converts this string to its ASCII lower case equivalent in-place. |
1025 | /// |
1026 | /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', |
1027 | /// but non-ASCII letters are unchanged. |
1028 | /// |
1029 | /// To return a new lowercased value without modifying the existing one, use |
1030 | /// [`OsStr::to_ascii_lowercase`]. |
1031 | /// |
1032 | /// # Examples |
1033 | /// |
1034 | /// ``` |
1035 | /// use std::ffi::OsString; |
1036 | /// |
1037 | /// let mut s = OsString::from("GRÜßE, JÜRGEN ❤" ); |
1038 | /// |
1039 | /// s.make_ascii_lowercase(); |
1040 | /// |
1041 | /// assert_eq!("grÜße, jÜrgen ❤" , s); |
1042 | /// ``` |
1043 | #[stable (feature = "osstring_ascii" , since = "1.53.0" )] |
1044 | #[inline ] |
1045 | pub fn make_ascii_lowercase(&mut self) { |
1046 | self.inner.make_ascii_lowercase() |
1047 | } |
1048 | |
1049 | /// Converts this string to its ASCII upper case equivalent in-place. |
1050 | /// |
1051 | /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', |
1052 | /// but non-ASCII letters are unchanged. |
1053 | /// |
1054 | /// To return a new uppercased value without modifying the existing one, use |
1055 | /// [`OsStr::to_ascii_uppercase`]. |
1056 | /// |
1057 | /// # Examples |
1058 | /// |
1059 | /// ``` |
1060 | /// use std::ffi::OsString; |
1061 | /// |
1062 | /// let mut s = OsString::from("Grüße, Jürgen ❤" ); |
1063 | /// |
1064 | /// s.make_ascii_uppercase(); |
1065 | /// |
1066 | /// assert_eq!("GRüßE, JüRGEN ❤" , s); |
1067 | /// ``` |
1068 | #[stable (feature = "osstring_ascii" , since = "1.53.0" )] |
1069 | #[inline ] |
1070 | pub fn make_ascii_uppercase(&mut self) { |
1071 | self.inner.make_ascii_uppercase() |
1072 | } |
1073 | |
1074 | /// Returns a copy of this string where each character is mapped to its |
1075 | /// ASCII lower case equivalent. |
1076 | /// |
1077 | /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', |
1078 | /// but non-ASCII letters are unchanged. |
1079 | /// |
1080 | /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`]. |
1081 | /// |
1082 | /// # Examples |
1083 | /// |
1084 | /// ``` |
1085 | /// use std::ffi::OsString; |
1086 | /// let s = OsString::from("Grüße, Jürgen ❤" ); |
1087 | /// |
1088 | /// assert_eq!("grüße, jürgen ❤" , s.to_ascii_lowercase()); |
1089 | /// ``` |
1090 | #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase`" ] |
1091 | #[stable (feature = "osstring_ascii" , since = "1.53.0" )] |
1092 | pub fn to_ascii_lowercase(&self) -> OsString { |
1093 | OsString::from_inner(self.inner.to_ascii_lowercase()) |
1094 | } |
1095 | |
1096 | /// Returns a copy of this string where each character is mapped to its |
1097 | /// ASCII upper case equivalent. |
1098 | /// |
1099 | /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', |
1100 | /// but non-ASCII letters are unchanged. |
1101 | /// |
1102 | /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`]. |
1103 | /// |
1104 | /// # Examples |
1105 | /// |
1106 | /// ``` |
1107 | /// use std::ffi::OsString; |
1108 | /// let s = OsString::from("Grüße, Jürgen ❤" ); |
1109 | /// |
1110 | /// assert_eq!("GRüßE, JüRGEN ❤" , s.to_ascii_uppercase()); |
1111 | /// ``` |
1112 | #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase`" ] |
1113 | #[stable (feature = "osstring_ascii" , since = "1.53.0" )] |
1114 | pub fn to_ascii_uppercase(&self) -> OsString { |
1115 | OsString::from_inner(self.inner.to_ascii_uppercase()) |
1116 | } |
1117 | |
1118 | /// Checks if all characters in this string are within the ASCII range. |
1119 | /// |
1120 | /// # Examples |
1121 | /// |
1122 | /// ``` |
1123 | /// use std::ffi::OsString; |
1124 | /// |
1125 | /// let ascii = OsString::from("hello! \n" ); |
1126 | /// let non_ascii = OsString::from("Grüße, Jürgen ❤" ); |
1127 | /// |
1128 | /// assert!(ascii.is_ascii()); |
1129 | /// assert!(!non_ascii.is_ascii()); |
1130 | /// ``` |
1131 | #[stable (feature = "osstring_ascii" , since = "1.53.0" )] |
1132 | #[must_use ] |
1133 | #[inline ] |
1134 | pub fn is_ascii(&self) -> bool { |
1135 | self.inner.is_ascii() |
1136 | } |
1137 | |
1138 | /// Checks that two strings are an ASCII case-insensitive match. |
1139 | /// |
1140 | /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`, |
1141 | /// but without allocating and copying temporaries. |
1142 | /// |
1143 | /// # Examples |
1144 | /// |
1145 | /// ``` |
1146 | /// use std::ffi::OsString; |
1147 | /// |
1148 | /// assert!(OsString::from("Ferris" ).eq_ignore_ascii_case("FERRIS" )); |
1149 | /// assert!(OsString::from("Ferrös" ).eq_ignore_ascii_case("FERRöS" )); |
1150 | /// assert!(!OsString::from("Ferrös" ).eq_ignore_ascii_case("FERRÖS" )); |
1151 | /// ``` |
1152 | #[stable (feature = "osstring_ascii" , since = "1.53.0" )] |
1153 | pub fn eq_ignore_ascii_case<S: AsRef<OsStr>>(&self, other: S) -> bool { |
1154 | self.inner.eq_ignore_ascii_case(&other.as_ref().inner) |
1155 | } |
1156 | |
1157 | /// Returns an object that implements [`Display`] for safely printing an |
1158 | /// [`OsStr`] that may contain non-Unicode data. This may perform lossy |
1159 | /// conversion, depending on the platform. If you would like an |
1160 | /// implementation which escapes the [`OsStr`] please use [`Debug`] |
1161 | /// instead. |
1162 | /// |
1163 | /// [`Display`]: fmt::Display |
1164 | /// [`Debug`]: fmt::Debug |
1165 | /// |
1166 | /// # Examples |
1167 | /// |
1168 | /// ``` |
1169 | /// #![feature(os_str_display)] |
1170 | /// use std::ffi::OsStr; |
1171 | /// |
1172 | /// let s = OsStr::new("Hello, world!" ); |
1173 | /// println!("{}" , s.display()); |
1174 | /// ``` |
1175 | #[unstable (feature = "os_str_display" , issue = "120048" )] |
1176 | #[must_use = "this does not display the `OsStr`; \ |
1177 | it returns an object that can be displayed" ] |
1178 | #[inline ] |
1179 | pub fn display(&self) -> Display<'_> { |
1180 | Display { os_str: self } |
1181 | } |
1182 | } |
1183 | |
1184 | #[stable (feature = "box_from_os_str" , since = "1.17.0" )] |
1185 | impl From<&OsStr> for Box<OsStr> { |
1186 | /// Copies the string into a newly allocated <code>[Box]<[OsStr]></code>. |
1187 | #[inline ] |
1188 | fn from(s: &OsStr) -> Box<OsStr> { |
1189 | let rw: *mut OsStr = Box::into_raw(s.inner.into_box()) as *mut OsStr; |
1190 | unsafe { Box::from_raw(rw) } |
1191 | } |
1192 | } |
1193 | |
1194 | #[stable (feature = "box_from_cow" , since = "1.45.0" )] |
1195 | impl From<Cow<'_, OsStr>> for Box<OsStr> { |
1196 | /// Converts a `Cow<'a, OsStr>` into a <code>[Box]<[OsStr]></code>, |
1197 | /// by copying the contents if they are borrowed. |
1198 | #[inline ] |
1199 | fn from(cow: Cow<'_, OsStr>) -> Box<OsStr> { |
1200 | match cow { |
1201 | Cow::Borrowed(s: &OsStr) => Box::from(s), |
1202 | Cow::Owned(s: OsString) => Box::from(s), |
1203 | } |
1204 | } |
1205 | } |
1206 | |
1207 | #[stable (feature = "os_string_from_box" , since = "1.18.0" )] |
1208 | impl From<Box<OsStr>> for OsString { |
1209 | /// Converts a <code>[Box]<[OsStr]></code> into an [`OsString`] without copying or |
1210 | /// allocating. |
1211 | #[inline ] |
1212 | fn from(boxed: Box<OsStr>) -> OsString { |
1213 | boxed.into_os_string() |
1214 | } |
1215 | } |
1216 | |
1217 | #[stable (feature = "box_from_os_string" , since = "1.20.0" )] |
1218 | impl From<OsString> for Box<OsStr> { |
1219 | /// Converts an [`OsString`] into a <code>[Box]<[OsStr]></code> without copying or allocating. |
1220 | #[inline ] |
1221 | fn from(s: OsString) -> Box<OsStr> { |
1222 | s.into_boxed_os_str() |
1223 | } |
1224 | } |
1225 | |
1226 | #[stable (feature = "more_box_slice_clone" , since = "1.29.0" )] |
1227 | impl Clone for Box<OsStr> { |
1228 | #[inline ] |
1229 | fn clone(&self) -> Self { |
1230 | self.to_os_string().into_boxed_os_str() |
1231 | } |
1232 | } |
1233 | |
1234 | #[stable (feature = "shared_from_slice2" , since = "1.24.0" )] |
1235 | impl From<OsString> for Arc<OsStr> { |
1236 | /// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> by moving the [`OsString`] |
1237 | /// data into a new [`Arc`] buffer. |
1238 | #[inline ] |
1239 | fn from(s: OsString) -> Arc<OsStr> { |
1240 | let arc: Arc = s.inner.into_arc(); |
1241 | unsafe { Arc::from_raw(ptr:Arc::into_raw(this:arc) as *const OsStr) } |
1242 | } |
1243 | } |
1244 | |
1245 | #[stable (feature = "shared_from_slice2" , since = "1.24.0" )] |
1246 | impl From<&OsStr> for Arc<OsStr> { |
1247 | /// Copies the string into a newly allocated <code>[Arc]<[OsStr]></code>. |
1248 | #[inline ] |
1249 | fn from(s: &OsStr) -> Arc<OsStr> { |
1250 | let arc: Arc = s.inner.into_arc(); |
1251 | unsafe { Arc::from_raw(ptr:Arc::into_raw(this:arc) as *const OsStr) } |
1252 | } |
1253 | } |
1254 | |
1255 | #[stable (feature = "shared_from_slice2" , since = "1.24.0" )] |
1256 | impl From<OsString> for Rc<OsStr> { |
1257 | /// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> by moving the [`OsString`] |
1258 | /// data into a new [`Rc`] buffer. |
1259 | #[inline ] |
1260 | fn from(s: OsString) -> Rc<OsStr> { |
1261 | let rc: Rc = s.inner.into_rc(); |
1262 | unsafe { Rc::from_raw(ptr:Rc::into_raw(this:rc) as *const OsStr) } |
1263 | } |
1264 | } |
1265 | |
1266 | #[stable (feature = "shared_from_slice2" , since = "1.24.0" )] |
1267 | impl From<&OsStr> for Rc<OsStr> { |
1268 | /// Copies the string into a newly allocated <code>[Rc]<[OsStr]></code>. |
1269 | #[inline ] |
1270 | fn from(s: &OsStr) -> Rc<OsStr> { |
1271 | let rc: Rc = s.inner.into_rc(); |
1272 | unsafe { Rc::from_raw(ptr:Rc::into_raw(this:rc) as *const OsStr) } |
1273 | } |
1274 | } |
1275 | |
1276 | #[stable (feature = "cow_from_osstr" , since = "1.28.0" )] |
1277 | impl<'a> From<OsString> for Cow<'a, OsStr> { |
1278 | /// Moves the string into a [`Cow::Owned`]. |
1279 | #[inline ] |
1280 | fn from(s: OsString) -> Cow<'a, OsStr> { |
1281 | Cow::Owned(s) |
1282 | } |
1283 | } |
1284 | |
1285 | #[stable (feature = "cow_from_osstr" , since = "1.28.0" )] |
1286 | impl<'a> From<&'a OsStr> for Cow<'a, OsStr> { |
1287 | /// Converts the string reference into a [`Cow::Borrowed`]. |
1288 | #[inline ] |
1289 | fn from(s: &'a OsStr) -> Cow<'a, OsStr> { |
1290 | Cow::Borrowed(s) |
1291 | } |
1292 | } |
1293 | |
1294 | #[stable (feature = "cow_from_osstr" , since = "1.28.0" )] |
1295 | impl<'a> From<&'a OsString> for Cow<'a, OsStr> { |
1296 | /// Converts the string reference into a [`Cow::Borrowed`]. |
1297 | #[inline ] |
1298 | fn from(s: &'a OsString) -> Cow<'a, OsStr> { |
1299 | Cow::Borrowed(s.as_os_str()) |
1300 | } |
1301 | } |
1302 | |
1303 | #[stable (feature = "osstring_from_cow_osstr" , since = "1.28.0" )] |
1304 | impl<'a> From<Cow<'a, OsStr>> for OsString { |
1305 | /// Converts a `Cow<'a, OsStr>` into an [`OsString`], |
1306 | /// by copying the contents if they are borrowed. |
1307 | #[inline ] |
1308 | fn from(s: Cow<'a, OsStr>) -> Self { |
1309 | s.into_owned() |
1310 | } |
1311 | } |
1312 | |
1313 | #[stable (feature = "str_tryfrom_osstr_impl" , since = "1.72.0" )] |
1314 | impl<'a> TryFrom<&'a OsStr> for &'a str { |
1315 | type Error = crate::str::Utf8Error; |
1316 | |
1317 | /// Tries to convert an `&OsStr` to a `&str`. |
1318 | /// |
1319 | /// ``` |
1320 | /// use std::ffi::OsStr; |
1321 | /// |
1322 | /// let os_str = OsStr::new("foo" ); |
1323 | /// let as_str = <&str>::try_from(os_str).unwrap(); |
1324 | /// assert_eq!(as_str, "foo" ); |
1325 | /// ``` |
1326 | fn try_from(value: &'a OsStr) -> Result<Self, Self::Error> { |
1327 | value.inner.to_str() |
1328 | } |
1329 | } |
1330 | |
1331 | #[stable (feature = "box_default_extra" , since = "1.17.0" )] |
1332 | impl Default for Box<OsStr> { |
1333 | #[inline ] |
1334 | fn default() -> Box<OsStr> { |
1335 | let rw: *mut OsStr = Box::into_raw(Slice::empty_box()) as *mut OsStr; |
1336 | unsafe { Box::from_raw(rw) } |
1337 | } |
1338 | } |
1339 | |
1340 | #[stable (feature = "osstring_default" , since = "1.9.0" )] |
1341 | impl Default for &OsStr { |
1342 | /// Creates an empty `OsStr`. |
1343 | #[inline ] |
1344 | fn default() -> Self { |
1345 | OsStr::new("" ) |
1346 | } |
1347 | } |
1348 | |
1349 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1350 | impl PartialEq for OsStr { |
1351 | #[inline ] |
1352 | fn eq(&self, other: &OsStr) -> bool { |
1353 | self.as_encoded_bytes().eq(other.as_encoded_bytes()) |
1354 | } |
1355 | } |
1356 | |
1357 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1358 | impl PartialEq<str> for OsStr { |
1359 | #[inline ] |
1360 | fn eq(&self, other: &str) -> bool { |
1361 | *self == *OsStr::new(other) |
1362 | } |
1363 | } |
1364 | |
1365 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1366 | impl PartialEq<OsStr> for str { |
1367 | #[inline ] |
1368 | fn eq(&self, other: &OsStr) -> bool { |
1369 | *other == *OsStr::new(self) |
1370 | } |
1371 | } |
1372 | |
1373 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1374 | impl Eq for OsStr {} |
1375 | |
1376 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1377 | impl PartialOrd for OsStr { |
1378 | #[inline ] |
1379 | fn partial_cmp(&self, other: &OsStr) -> Option<cmp::Ordering> { |
1380 | self.as_encoded_bytes().partial_cmp(other.as_encoded_bytes()) |
1381 | } |
1382 | #[inline ] |
1383 | fn lt(&self, other: &OsStr) -> bool { |
1384 | self.as_encoded_bytes().lt(other.as_encoded_bytes()) |
1385 | } |
1386 | #[inline ] |
1387 | fn le(&self, other: &OsStr) -> bool { |
1388 | self.as_encoded_bytes().le(other.as_encoded_bytes()) |
1389 | } |
1390 | #[inline ] |
1391 | fn gt(&self, other: &OsStr) -> bool { |
1392 | self.as_encoded_bytes().gt(other.as_encoded_bytes()) |
1393 | } |
1394 | #[inline ] |
1395 | fn ge(&self, other: &OsStr) -> bool { |
1396 | self.as_encoded_bytes().ge(other.as_encoded_bytes()) |
1397 | } |
1398 | } |
1399 | |
1400 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1401 | impl PartialOrd<str> for OsStr { |
1402 | #[inline ] |
1403 | fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> { |
1404 | self.partial_cmp(OsStr::new(other)) |
1405 | } |
1406 | } |
1407 | |
1408 | // FIXME (#19470): cannot provide PartialOrd<OsStr> for str until we |
1409 | // have more flexible coherence rules. |
1410 | |
1411 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1412 | impl Ord for OsStr { |
1413 | #[inline ] |
1414 | fn cmp(&self, other: &OsStr) -> cmp::Ordering { |
1415 | self.as_encoded_bytes().cmp(other.as_encoded_bytes()) |
1416 | } |
1417 | } |
1418 | |
1419 | macro_rules! impl_cmp { |
1420 | ($lhs:ty, $rhs: ty) => { |
1421 | #[stable(feature = "cmp_os_str" , since = "1.8.0" )] |
1422 | impl<'a, 'b> PartialEq<$rhs> for $lhs { |
1423 | #[inline] |
1424 | fn eq(&self, other: &$rhs) -> bool { |
1425 | <OsStr as PartialEq>::eq(self, other) |
1426 | } |
1427 | } |
1428 | |
1429 | #[stable(feature = "cmp_os_str" , since = "1.8.0" )] |
1430 | impl<'a, 'b> PartialEq<$lhs> for $rhs { |
1431 | #[inline] |
1432 | fn eq(&self, other: &$lhs) -> bool { |
1433 | <OsStr as PartialEq>::eq(self, other) |
1434 | } |
1435 | } |
1436 | |
1437 | #[stable(feature = "cmp_os_str" , since = "1.8.0" )] |
1438 | impl<'a, 'b> PartialOrd<$rhs> for $lhs { |
1439 | #[inline] |
1440 | fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> { |
1441 | <OsStr as PartialOrd>::partial_cmp(self, other) |
1442 | } |
1443 | } |
1444 | |
1445 | #[stable(feature = "cmp_os_str" , since = "1.8.0" )] |
1446 | impl<'a, 'b> PartialOrd<$lhs> for $rhs { |
1447 | #[inline] |
1448 | fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> { |
1449 | <OsStr as PartialOrd>::partial_cmp(self, other) |
1450 | } |
1451 | } |
1452 | }; |
1453 | } |
1454 | |
1455 | impl_cmp!(OsString, OsStr); |
1456 | impl_cmp!(OsString, &'a OsStr); |
1457 | impl_cmp!(Cow<'a, OsStr>, OsStr); |
1458 | impl_cmp!(Cow<'a, OsStr>, &'b OsStr); |
1459 | impl_cmp!(Cow<'a, OsStr>, OsString); |
1460 | |
1461 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1462 | impl Hash for OsStr { |
1463 | #[inline ] |
1464 | fn hash<H: Hasher>(&self, state: &mut H) { |
1465 | self.as_encoded_bytes().hash(state) |
1466 | } |
1467 | } |
1468 | |
1469 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1470 | impl fmt::Debug for OsStr { |
1471 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
1472 | fmt::Debug::fmt(&self.inner, f:formatter) |
1473 | } |
1474 | } |
1475 | |
1476 | /// Helper struct for safely printing an [`OsStr`] with [`format!`] and `{}`. |
1477 | /// |
1478 | /// An [`OsStr`] might contain non-Unicode data. This `struct` implements the |
1479 | /// [`Display`] trait in a way that mitigates that. It is created by the |
1480 | /// [`display`](OsStr::display) method on [`OsStr`]. This may perform lossy |
1481 | /// conversion, depending on the platform. If you would like an implementation |
1482 | /// which escapes the [`OsStr`] please use [`Debug`] instead. |
1483 | /// |
1484 | /// # Examples |
1485 | /// |
1486 | /// ``` |
1487 | /// #![feature(os_str_display)] |
1488 | /// use std::ffi::OsStr; |
1489 | /// |
1490 | /// let s = OsStr::new("Hello, world!" ); |
1491 | /// println!("{}" , s.display()); |
1492 | /// ``` |
1493 | /// |
1494 | /// [`Display`]: fmt::Display |
1495 | /// [`format!`]: crate::format |
1496 | #[unstable (feature = "os_str_display" , issue = "120048" )] |
1497 | pub struct Display<'a> { |
1498 | os_str: &'a OsStr, |
1499 | } |
1500 | |
1501 | #[unstable (feature = "os_str_display" , issue = "120048" )] |
1502 | impl fmt::Debug for Display<'_> { |
1503 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1504 | fmt::Debug::fmt(&self.os_str, f) |
1505 | } |
1506 | } |
1507 | |
1508 | #[unstable (feature = "os_str_display" , issue = "120048" )] |
1509 | impl fmt::Display for Display<'_> { |
1510 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1511 | fmt::Display::fmt(&self.os_str.inner, f) |
1512 | } |
1513 | } |
1514 | |
1515 | #[unstable (feature = "slice_concat_ext" , issue = "27747" )] |
1516 | impl<S: Borrow<OsStr>> alloc::slice::Join<&OsStr> for [S] { |
1517 | type Output = OsString; |
1518 | |
1519 | fn join(slice: &Self, sep: &OsStr) -> OsString { |
1520 | let Some((first: &S, suffix: &[S])) = slice.split_first() else { |
1521 | return OsString::new(); |
1522 | }; |
1523 | let first_owned: OsString = first.borrow().to_owned(); |
1524 | suffix.iter().fold(init:first_owned, |mut a: OsString, b: &S| { |
1525 | a.push(sep); |
1526 | a.push(b.borrow()); |
1527 | a |
1528 | }) |
1529 | } |
1530 | } |
1531 | |
1532 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1533 | impl Borrow<OsStr> for OsString { |
1534 | #[inline ] |
1535 | fn borrow(&self) -> &OsStr { |
1536 | &self[..] |
1537 | } |
1538 | } |
1539 | |
1540 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1541 | impl ToOwned for OsStr { |
1542 | type Owned = OsString; |
1543 | #[inline ] |
1544 | fn to_owned(&self) -> OsString { |
1545 | self.to_os_string() |
1546 | } |
1547 | #[inline ] |
1548 | fn clone_into(&self, target: &mut OsString) { |
1549 | self.inner.clone_into(&mut target.inner) |
1550 | } |
1551 | } |
1552 | |
1553 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1554 | impl AsRef<OsStr> for OsStr { |
1555 | #[inline ] |
1556 | fn as_ref(&self) -> &OsStr { |
1557 | self |
1558 | } |
1559 | } |
1560 | |
1561 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1562 | impl AsRef<OsStr> for OsString { |
1563 | #[inline ] |
1564 | fn as_ref(&self) -> &OsStr { |
1565 | self |
1566 | } |
1567 | } |
1568 | |
1569 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1570 | impl AsRef<OsStr> for str { |
1571 | #[inline ] |
1572 | fn as_ref(&self) -> &OsStr { |
1573 | OsStr::from_inner(Slice::from_str(self)) |
1574 | } |
1575 | } |
1576 | |
1577 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1578 | impl AsRef<OsStr> for String { |
1579 | #[inline ] |
1580 | fn as_ref(&self) -> &OsStr { |
1581 | (&**self).as_ref() |
1582 | } |
1583 | } |
1584 | |
1585 | impl FromInner<Buf> for OsString { |
1586 | #[inline ] |
1587 | fn from_inner(buf: Buf) -> OsString { |
1588 | OsString { inner: buf } |
1589 | } |
1590 | } |
1591 | |
1592 | impl IntoInner<Buf> for OsString { |
1593 | #[inline ] |
1594 | fn into_inner(self) -> Buf { |
1595 | self.inner |
1596 | } |
1597 | } |
1598 | |
1599 | impl AsInner<Slice> for OsStr { |
1600 | #[inline ] |
1601 | fn as_inner(&self) -> &Slice { |
1602 | &self.inner |
1603 | } |
1604 | } |
1605 | |
1606 | #[stable (feature = "osstring_from_str" , since = "1.45.0" )] |
1607 | impl FromStr for OsString { |
1608 | type Err = core::convert::Infallible; |
1609 | |
1610 | #[inline ] |
1611 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
1612 | Ok(OsString::from(s)) |
1613 | } |
1614 | } |
1615 | |
1616 | #[stable (feature = "osstring_extend" , since = "1.52.0" )] |
1617 | impl Extend<OsString> for OsString { |
1618 | #[inline ] |
1619 | fn extend<T: IntoIterator<Item = OsString>>(&mut self, iter: T) { |
1620 | for s: OsString in iter { |
1621 | self.push(&s); |
1622 | } |
1623 | } |
1624 | } |
1625 | |
1626 | #[stable (feature = "osstring_extend" , since = "1.52.0" )] |
1627 | impl<'a> Extend<&'a OsStr> for OsString { |
1628 | #[inline ] |
1629 | fn extend<T: IntoIterator<Item = &'a OsStr>>(&mut self, iter: T) { |
1630 | for s: &OsStr in iter { |
1631 | self.push(s); |
1632 | } |
1633 | } |
1634 | } |
1635 | |
1636 | #[stable (feature = "osstring_extend" , since = "1.52.0" )] |
1637 | impl<'a> Extend<Cow<'a, OsStr>> for OsString { |
1638 | #[inline ] |
1639 | fn extend<T: IntoIterator<Item = Cow<'a, OsStr>>>(&mut self, iter: T) { |
1640 | for s: Cow<'_, OsStr> in iter { |
1641 | self.push(&s); |
1642 | } |
1643 | } |
1644 | } |
1645 | |
1646 | #[stable (feature = "osstring_extend" , since = "1.52.0" )] |
1647 | impl FromIterator<OsString> for OsString { |
1648 | #[inline ] |
1649 | fn from_iter<I: IntoIterator<Item = OsString>>(iter: I) -> Self { |
1650 | let mut iterator: ::IntoIter = iter.into_iter(); |
1651 | |
1652 | // Because we're iterating over `OsString`s, we can avoid at least |
1653 | // one allocation by getting the first string from the iterator |
1654 | // and appending to it all the subsequent strings. |
1655 | match iterator.next() { |
1656 | None => OsString::new(), |
1657 | Some(mut buf: OsString) => { |
1658 | buf.extend(iter:iterator); |
1659 | buf |
1660 | } |
1661 | } |
1662 | } |
1663 | } |
1664 | |
1665 | #[stable (feature = "osstring_extend" , since = "1.52.0" )] |
1666 | impl<'a> FromIterator<&'a OsStr> for OsString { |
1667 | #[inline ] |
1668 | fn from_iter<I: IntoIterator<Item = &'a OsStr>>(iter: I) -> Self { |
1669 | let mut buf: OsString = Self::new(); |
1670 | for s: &OsStr in iter { |
1671 | buf.push(s); |
1672 | } |
1673 | buf |
1674 | } |
1675 | } |
1676 | |
1677 | #[stable (feature = "osstring_extend" , since = "1.52.0" )] |
1678 | impl<'a> FromIterator<Cow<'a, OsStr>> for OsString { |
1679 | #[inline ] |
1680 | fn from_iter<I: IntoIterator<Item = Cow<'a, OsStr>>>(iter: I) -> Self { |
1681 | let mut iterator: ::IntoIter = iter.into_iter(); |
1682 | |
1683 | // Because we're iterating over `OsString`s, we can avoid at least |
1684 | // one allocation by getting the first owned string from the iterator |
1685 | // and appending to it all the subsequent strings. |
1686 | match iterator.next() { |
1687 | None => OsString::new(), |
1688 | Some(Cow::Owned(mut buf: OsString)) => { |
1689 | buf.extend(iter:iterator); |
1690 | buf |
1691 | } |
1692 | Some(Cow::Borrowed(buf: &OsStr)) => { |
1693 | let mut buf: OsString = OsString::from(buf); |
1694 | buf.extend(iter:iterator); |
1695 | buf |
1696 | } |
1697 | } |
1698 | } |
1699 | } |
1700 | |