Skip to content

Commit b3b7c2e

Browse files
author
root
committed
core: Separate failure formatting in str methods slice, slice_to, slice_from
Use a separate inline-never function to format failure message for str::slice() errors. Using strcat's idea, this makes sure no formatting code from failure is inlined when str::slice() is inlined. The number of `unreachable` being inlined when usingi `.slice()` drops from 5 to just 1.
1 parent 58bb603 commit b3b7c2e

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

src/libcore/str.rs

+31-11
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,13 @@ pub trait StrSlice<'a> {
17051705
fn utf16_units(&self) -> Utf16CodeUnits<'a>;
17061706
}
17071707

1708+
#[inline(never)]
1709+
fn slice_error_fail(s: &str, begin: uint, end: uint) -> ! {
1710+
assert!(begin <= end);
1711+
fail!("index {} and/or {} in `{}` do not lie on character boundary",
1712+
begin, end, s);
1713+
}
1714+
17081715
impl<'a> StrSlice<'a> for &'a str {
17091716
#[inline]
17101717
fn contains<'a>(&self, needle: &'a str) -> bool {
@@ -1808,22 +1815,34 @@ impl<'a> StrSlice<'a> for &'a str {
18081815

18091816
#[inline]
18101817
fn slice(&self, begin: uint, end: uint) -> &'a str {
1811-
assert!(self.is_char_boundary(begin) && self.is_char_boundary(end),
1812-
"index {} and/or {} in `{}` do not lie on character boundary", begin,
1813-
end, *self);
1814-
unsafe { raw::slice_bytes(*self, begin, end) }
1818+
// is_char_boundary checks that the index is in [0, .len()]
1819+
if begin <= end &&
1820+
self.is_char_boundary(begin) &&
1821+
self.is_char_boundary(end) {
1822+
unsafe { raw::slice_unchecked(*self, begin, end) }
1823+
} else {
1824+
slice_error_fail(*self, begin, end)
1825+
}
18151826
}
18161827

18171828
#[inline]
18181829
fn slice_from(&self, begin: uint) -> &'a str {
1819-
self.slice(begin, self.len())
1830+
// is_char_boundary checks that the index is in [0, .len()]
1831+
if self.is_char_boundary(begin) {
1832+
unsafe { raw::slice_unchecked(*self, begin, self.len()) }
1833+
} else {
1834+
slice_error_fail(*self, begin, self.len())
1835+
}
18201836
}
18211837

18221838
#[inline]
18231839
fn slice_to(&self, end: uint) -> &'a str {
1824-
assert!(self.is_char_boundary(end), "index {} in `{}` does not lie on \
1825-
a character boundary", end, *self);
1826-
unsafe { raw::slice_bytes(*self, 0, end) }
1840+
// is_char_boundary checks that the index is in [0, .len()]
1841+
if self.is_char_boundary(end) {
1842+
unsafe { raw::slice_unchecked(*self, 0, end) }
1843+
} else {
1844+
slice_error_fail(*self, 0, end)
1845+
}
18271846
}
18281847

18291848
fn slice_chars(&self, begin: uint, end: uint) -> &'a str {
@@ -1898,9 +1917,10 @@ impl<'a> StrSlice<'a> for &'a str {
18981917
#[inline]
18991918
fn is_char_boundary(&self, index: uint) -> bool {
19001919
if index == self.len() { return true; }
1901-
if index > self.len() { return false; }
1902-
let b = self.as_bytes()[index];
1903-
return b < 128u8 || b >= 192u8;
1920+
match self.as_bytes().get(index) {
1921+
None => false,
1922+
Some(&b) => b < 128u8 || b >= 192u8,
1923+
}
19041924
}
19051925

19061926
#[inline]

0 commit comments

Comments
 (0)