about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-07-13 23:47:06 +0000
committerbors <bors@rust-lang.org>2015-07-13 23:47:06 +0000
commitdd46cf8b22c39a74b786361e00af22314a32b196 (patch)
treeef42015a6a4e59fe77648d41ca5a79f4e0cdb21f /src/libcore
parent72483f58e355c6ec9016cbaba4d9b8d3adbd3867 (diff)
parent3226858e500fa70b46c18d1accedc60060f2bbc0 (diff)
downloadrust-dd46cf8b22c39a74b786361e00af22314a32b196.tar.gz
rust-dd46cf8b22c39a74b786361e00af22314a32b196.zip
Auto merge of #26241 - SimonSapin:derefmut-for-string, r=alexcrichton
See https://github.com/rust-lang/rfcs/issues/1157
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/str/mod.rs79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index bd6e1a4063a..7e4c2ba3be8 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1116,6 +1116,23 @@ mod traits {
         }
     }
 
+    /// Returns a mutable slice of the given string from the byte range
+    /// [`begin`..`end`).
+    #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+    impl ops::IndexMut<ops::Range<usize>> for str {
+        #[inline]
+        fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
+            // is_char_boundary checks that the index is in [0, .len()]
+            if index.start <= index.end &&
+               self.is_char_boundary(index.start) &&
+               self.is_char_boundary(index.end) {
+                unsafe { self.slice_mut_unchecked(index.start, index.end) }
+            } else {
+                super::slice_error_fail(self, index.start, index.end)
+            }
+        }
+    }
+
     /// Returns a slice of the string from the beginning to byte
     /// `end`.
     ///
@@ -1138,6 +1155,21 @@ mod traits {
         }
     }
 
+    /// Returns a mutable slice of the string from the beginning to byte
+    /// `end`.
+    #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+    impl ops::IndexMut<ops::RangeTo<usize>> for str {
+        #[inline]
+        fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
+            // is_char_boundary checks that the index is in [0, .len()]
+            if self.is_char_boundary(index.end) {
+                unsafe { self.slice_mut_unchecked(0, index.end) }
+            } else {
+                super::slice_error_fail(self, 0, index.end)
+            }
+        }
+    }
+
     /// Returns a slice of the string from `begin` to its end.
     ///
     /// Equivalent to `self[begin .. self.len()]`.
@@ -1159,6 +1191,21 @@ mod traits {
         }
     }
 
+    /// Returns a slice of the string from `begin` to its end.
+    #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+    impl ops::IndexMut<ops::RangeFrom<usize>> for str {
+        #[inline]
+        fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
+            // is_char_boundary checks that the index is in [0, .len()]
+            if self.is_char_boundary(index.start) {
+                let len = self.len();
+                unsafe { self.slice_mut_unchecked(index.start, len) }
+            } else {
+                super::slice_error_fail(self, index.start, self.len())
+            }
+        }
+    }
+
     #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::RangeFull> for str {
         type Output = str;
@@ -1168,6 +1215,14 @@ mod traits {
             self
         }
     }
+
+    #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+    impl ops::IndexMut<ops::RangeFull> for str {
+        #[inline]
+        fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
+            self
+        }
+    }
 }
 
 /// Methods for string slices
@@ -1204,6 +1259,7 @@ pub trait StrExt {
     fn char_len(&self) -> usize;
     fn slice_chars<'a>(&'a self, begin: usize, end: usize) -> &'a str;
     unsafe fn slice_unchecked<'a>(&'a self, begin: usize, end: usize) -> &'a str;
+    unsafe fn slice_mut_unchecked<'a>(&'a mut self, begin: usize, end: usize) -> &'a mut str;
     fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool;
     fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
         where P::Searcher: ReverseSearcher<'a>;
@@ -1223,6 +1279,7 @@ pub trait StrExt {
         where P::Searcher: ReverseSearcher<'a>;
     fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
     fn split_at(&self, mid: usize) -> (&str, &str);
+    fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str);
     fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
     fn subslice_offset(&self, inner: &str) -> usize;
     fn as_ptr(&self) -> *const u8;
@@ -1380,6 +1437,14 @@ impl StrExt for str {
     }
 
     #[inline]
+    unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
+        mem::transmute(Slice {
+            data: self.as_ptr().offset(begin as isize),
+            len: end - begin,
+        })
+    }
+
+    #[inline]
     fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
         pat.is_prefix_of(self)
     }
@@ -1527,6 +1592,20 @@ impl StrExt for str {
         }
     }
 
+    fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
+        // is_char_boundary checks that the index is in [0, .len()]
+        if self.is_char_boundary(mid) {
+            let len = self.len();
+            unsafe {
+                let self2: &mut str = mem::transmute_copy(&self);
+                (self.slice_mut_unchecked(0, mid),
+                 self2.slice_mut_unchecked(mid, len))
+            }
+        } else {
+            slice_error_fail(self, 0, mid)
+        }
+    }
+
     #[inline]
     fn slice_shift_char(&self) -> Option<(char, &str)> {
         if self.is_empty() {