Skip to content

Commit ac85082

Browse files
author
Ulrik Sverdrup
committed
Add str::split_at
Implement RFC rust-lang/rfcs#1123 Add str method str::split_at(mid: usize) -> (&str, &str).
1 parent 541fe5f commit ac85082

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

src/libcollections/str.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,32 @@ impl str {
15561556
core_str::StrExt::rfind(&self[..], pat)
15571557
}
15581558

1559+
/// Divide one string slice into two at an index.
1560+
///
1561+
/// The index `mid` is a byte offset from the start of the string
1562+
/// that must be on a character boundary.
1563+
///
1564+
/// Return slices `&self[..mid]` and `&self[mid..]`.
1565+
///
1566+
/// # Panics
1567+
///
1568+
/// Panics if `mid` is beyond the last character of the string,
1569+
/// or if it is not on a character boundary.
1570+
///
1571+
/// # Examples
1572+
/// ```
1573+
/// let s = "Löwe 老虎 Léopard";
1574+
/// let first_space = s.find(' ').unwrap_or(s.len());
1575+
/// let (a, b) = s.split_at(first_space);
1576+
///
1577+
/// assert_eq!(a, "Löwe");
1578+
/// assert_eq!(b, " 老虎 Léopard");
1579+
/// ```
1580+
#[inline]
1581+
pub fn split_at(&self, mid: usize) -> (&str, &str) {
1582+
core_str::StrExt::split_at(self, mid)
1583+
}
1584+
15591585
/// Retrieves the first character from a `&str` and returns it.
15601586
///
15611587
/// This does not allocate a new string; instead, it returns a slice that

src/libcollectionstest/str.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,26 @@ fn test_char_at_reverse() {
688688
}
689689
}
690690

691+
#[test]
692+
fn test_split_at() {
693+
let s = "ศไทย中华Việt Nam";
694+
for (index, _) in s.char_indices() {
695+
let (a, b) = s.split_at(index);
696+
assert_eq!(&s[..a.len()], a);
697+
assert_eq!(&s[a.len()..], b);
698+
}
699+
let (a, b) = s.split_at(s.len());
700+
assert_eq!(a, s);
701+
assert_eq!(b, "");
702+
}
703+
704+
#[test]
705+
#[should_panic]
706+
fn test_split_at_boundscheck() {
707+
let s = "ศไทย中华Việt Nam";
708+
let (a, b) = s.split_at(1);
709+
}
710+
691711
#[test]
692712
fn test_escape_unicode() {
693713
assert_eq!("abc".escape_unicode(),

src/libcore/str/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,7 @@ pub trait StrExt {
15171517
fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
15181518
where P::Searcher: ReverseSearcher<'a>;
15191519
fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
1520+
fn split_at(&self, mid: usize) -> (&str, &str);
15201521
fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
15211522
fn subslice_offset(&self, inner: &str) -> usize;
15221523
fn as_ptr(&self) -> *const u8;
@@ -1809,6 +1810,18 @@ impl StrExt for str {
18091810
self.find(pat)
18101811
}
18111812

1813+
fn split_at(&self, mid: usize) -> (&str, &str) {
1814+
// is_char_boundary checks that the index is in [0, .len()]
1815+
if self.is_char_boundary(mid) {
1816+
unsafe {
1817+
(self.slice_unchecked(0, mid),
1818+
self.slice_unchecked(mid, self.len()))
1819+
}
1820+
} else {
1821+
slice_error_fail(self, 0, mid)
1822+
}
1823+
}
1824+
18121825
#[inline]
18131826
fn slice_shift_char(&self) -> Option<(char, &str)> {
18141827
if self.is_empty() {

0 commit comments

Comments
 (0)