about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorUlrik Sverdrup <root@localhost>2015-06-09 11:23:22 +0200
committerUlrik Sverdrup <root@localhost>2015-06-10 09:15:07 +0200
commitd43bf539482b8244690824e0880a80ed578d5429 (patch)
tree0d1e48d33e06ba667ceeb1b198aa774938d5765a /src
parent6daf1dcb80e324df94ad4a1d263c832ab589b33a (diff)
downloadrust-d43bf539482b8244690824e0880a80ed578d5429.tar.gz
rust-d43bf539482b8244690824e0880a80ed578d5429.zip
Add str::split_at
Implement RFC rust-lang/rfcs#1123

Add str method str::split_at(mid: usize) -> (&str, &str).
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/str.rs27
-rw-r--r--src/libcollectionstest/str.rs20
-rw-r--r--src/libcore/str/mod.rs13
3 files changed, 60 insertions, 0 deletions
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index a9725214c19..062f7992724 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -779,6 +779,33 @@ impl str {
         core_str::StrExt::slice_shift_char(&self[..])
     }
 
+    /// Divide one string slice into two at an index.
+    ///
+    /// The index `mid` is a byte offset from the start of the string
+    /// that must be on a character boundary.
+    ///
+    /// Return slices `&self[..mid]` and `&self[mid..]`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid` is beyond the last character of the string,
+    /// or if it is not on a character boundary.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(collections)]
+    /// let s = "Löwe 老虎 Léopard";
+    /// let first_space = s.find(' ').unwrap_or(s.len());
+    /// let (a, b) = s.split_at(first_space);
+    ///
+    /// assert_eq!(a, "Löwe");
+    /// assert_eq!(b, " 老虎 Léopard");
+    /// ```
+    #[inline]
+    pub fn split_at(&self, mid: usize) -> (&str, &str) {
+        core_str::StrExt::split_at(self, mid)
+    }
+
     /// An iterator over the codepoints of `self`.
     ///
     /// # Examples
diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs
index 1019e98153e..def79682801 100644
--- a/src/libcollectionstest/str.rs
+++ b/src/libcollectionstest/str.rs
@@ -689,6 +689,26 @@ fn test_char_at_reverse() {
 }
 
 #[test]
+fn test_split_at() {
+    let s = "ศไทย中华Việt Nam";
+    for (index, _) in s.char_indices() {
+        let (a, b) = s.split_at(index);
+        assert_eq!(&s[..a.len()], a);
+        assert_eq!(&s[a.len()..], b);
+    }
+    let (a, b) = s.split_at(s.len());
+    assert_eq!(a, s);
+    assert_eq!(b, "");
+}
+
+#[test]
+#[should_panic]
+fn test_split_at_boundscheck() {
+    let s = "ศไทย中华Việt Nam";
+    let (a, b) = s.split_at(1);
+}
+
+#[test]
 fn test_escape_unicode() {
     assert_eq!("abc".escape_unicode(),
                String::from("\\u{61}\\u{62}\\u{63}"));
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 11ca6e332b5..4db64a3097e 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1517,6 +1517,7 @@ pub trait StrExt {
     fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
         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 slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
     fn subslice_offset(&self, inner: &str) -> usize;
     fn as_ptr(&self) -> *const u8;
@@ -1809,6 +1810,18 @@ impl StrExt for str {
         self.find(pat)
     }
 
+    fn split_at(&self, mid: usize) -> (&str, &str) {
+        // is_char_boundary checks that the index is in [0, .len()]
+        if self.is_char_boundary(mid) {
+            unsafe {
+                (self.slice_unchecked(0, mid),
+                 self.slice_unchecked(mid, self.len()))
+            }
+        } else {
+            slice_error_fail(self, 0, mid)
+        }
+    }
+
     #[inline]
     fn slice_shift_char(&self) -> Option<(char, &str)> {
         if self.is_empty() {