summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-03-27 01:23:51 +0100
committerGitHub <noreply@github.com>2020-03-27 01:23:51 +0100
commitc0369c4523caecda8af40f4eb84509b42b673d85 (patch)
treec2568402f662316d31a8d77fa2c651673190dc8f
parentRollup merge of #69936 - Aaron1011:fix/suggestion-cycle, r=varkor (diff)
parentadd comment about maintaining OsStr encoding (diff)
downloadrust-c0369c4523caecda8af40f4eb84509b42b673d85.tar.gz
rust-c0369c4523caecda8af40f4eb84509b42b673d85.tar.bz2
rust-c0369c4523caecda8af40f4eb84509b42b673d85.tar.xz
Rollup merge of #70048 - TyPR124:mutable_osstr, r=dtolnay
Allow obtaining &mut OsStr ```rust impl DerefMut for OsString {...} // type Target = OsStr impl IndexMut<RangeFull> for OsString {...} // type Output = OsStr ``` --- This change is pulled out of #69937 per @dtolnay This implements `DerefMut for OsString` to allow obtaining a `&mut OsStr`. This also implements `IndexMut for OsString`, which is used by `DerefMut`. This pattern is the same as is used by `Deref`. This is necessary to for methods like `make_ascii_lowercase` which need to mutate the underlying value.
-rw-r--r--src/libstd/ffi/os_str.rs27
-rw-r--r--src/libstd/sys/windows/os_str.rs12
-rw-r--r--src/libstd/sys_common/os_str_bytes.rs11
3 files changed, 50 insertions, 0 deletions
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index 77da972..0fbe8e5 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -379,6 +379,14 @@ impl ops::Index<ops::RangeFull> for OsString {
379 } 379 }
380} 380}
381 381
382#[stable(feature = "mut_osstr", since = "1.44.0")]
383impl ops::IndexMut<ops::RangeFull> for OsString {
384 #[inline]
385 fn index_mut(&mut self, _index: ops::RangeFull) -> &mut OsStr {
386 OsStr::from_inner_mut(self.inner.as_mut_slice())
387 }
388}
389
382#[stable(feature = "rust1", since = "1.0.0")] 390#[stable(feature = "rust1", since = "1.0.0")]
383impl ops::Deref for OsString { 391impl ops::Deref for OsString {
384 type Target = OsStr; 392 type Target = OsStr;
@@ -389,6 +397,14 @@ impl ops::Deref for OsString {
389 } 397 }
390} 398}
391 399
400#[stable(feature = "mut_osstr", since = "1.44.0")]
401impl ops::DerefMut for OsString {
402 #[inline]
403 fn deref_mut(&mut self) -> &mut OsStr {
404 &mut self[..]
405 }
406}
407
392#[stable(feature = "osstring_default", since = "1.9.0")] 408#[stable(feature = "osstring_default", since = "1.9.0")]
393impl Default for OsString { 409impl Default for OsString {
394 /// Constructs an empty `OsString`. 410 /// Constructs an empty `OsString`.
@@ -509,9 +525,20 @@ impl OsStr {
509 525
510 #[inline] 526 #[inline]
511 fn from_inner(inner: &Slice) -> &OsStr { 527 fn from_inner(inner: &Slice) -> &OsStr {
528 // Safety: OsStr is just a wrapper of Slice,
529 // therefore converting &Slice to &OsStr is safe.
512 unsafe { &*(inner as *const Slice as *const OsStr) } 530 unsafe { &*(inner as *const Slice as *const OsStr) }
513 } 531 }
514 532
533 #[inline]
534 fn from_inner_mut(inner: &mut Slice) -> &mut OsStr {
535 // Safety: OsStr is just a wrapper of Slice,
536 // therefore converting &mut Slice to &mut OsStr is safe.
537 // Any method that mutates OsStr must be careful not to
538 // break platform-specific encoding, in particular Wtf8 on Windows.
539 unsafe { &mut *(inner as *mut Slice as *mut OsStr) }
540 }
541
515 /// Yields a [`&str`] slice if the `OsStr` is valid Unicode. 542 /// Yields a [`&str`] slice if the `OsStr` is valid Unicode.
516 /// 543 ///
517 /// This conversion may entail doing a check for UTF-8 validity. 544 /// This conversion may entail doing a check for UTF-8 validity.
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index ef260f9..ff6885c 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -77,9 +77,21 @@ impl Buf {
77 } 77 }
78 78
79 pub fn as_slice(&self) -> &Slice { 79 pub fn as_slice(&self) -> &Slice {
80 // Safety: Slice is just a wrapper for Wtf8,
81 // and self.inner.as_slice() returns &Wtf8.
82 // Therefore, transmuting &Wtf8 to &Slice is safe.
80 unsafe { mem::transmute(self.inner.as_slice()) } 83 unsafe { mem::transmute(self.inner.as_slice()) }
81 } 84 }
82 85
86 pub fn as_mut_slice(&mut self) -> &mut Slice {
87 // Safety: Slice is just a wrapper for Wtf8,
88 // and self.inner.as_mut_slice() returns &mut Wtf8.
89 // Therefore, transmuting &mut Wtf8 to &mut Slice is safe.
90 // Additionally, care should be taken to ensure the slice
91 // is always valid Wtf8.
92 unsafe { mem::transmute(self.inner.as_mut_slice()) }
93 }
94
83 pub fn into_string(self) -> Result<String, Buf> { 95 pub fn into_string(self) -> Result<String, Buf> {
84 self.inner.into_string().map_err(|buf| Buf { inner: buf }) 96 self.inner.into_string().map_err(|buf| Buf { inner: buf })
85 } 97 }
diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs
index e965ea7..c5d02fb 100644
--- a/src/libstd/sys_common/os_str_bytes.rs
+++ b/src/libstd/sys_common/os_str_bytes.rs
@@ -106,9 +106,20 @@ impl Buf {
106 106
107 #[inline] 107 #[inline]
108 pub fn as_slice(&self) -> &Slice { 108 pub fn as_slice(&self) -> &Slice {
109 // Safety: Slice just wraps [u8],
110 // and &*self.inner is &[u8], therefore
111 // transmuting &[u8] to &Slice is safe.
109 unsafe { mem::transmute(&*self.inner) } 112 unsafe { mem::transmute(&*self.inner) }
110 } 113 }
111 114
115 #[inline]
116 pub fn as_mut_slice(&mut self) -> &mut Slice {
117 // Safety: Slice just wraps [u8],
118 // and &mut *self.inner is &mut [u8], therefore
119 // transmuting &mut [u8] to &mut Slice is safe.
120 unsafe { mem::transmute(&mut *self.inner) }
121 }
122
112 pub fn into_string(self) -> Result<String, Buf> { 123 pub fn into_string(self) -> Result<String, Buf> {
113 String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() }) 124 String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() })
114 } 125 }