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