diff options
| author | root <root@localhost> | 2014-08-23 12:30:08 +0200 |
|---|---|---|
| committer | root <root@localhost> | 2014-08-23 13:49:19 +0200 |
| commit | b3b7c2e97b8e34ebc2597c21653df4b2d7a37575 (patch) | |
| tree | 1353cdc9d2cc4cdfd2e523610c6acf0b4ed3e451 | |
| parent | 58bb603ea74a388d7a4dafc0c78f214a46301505 (diff) | |
| download | rust-b3b7c2e97b8e34ebc2597c21653df4b2d7a37575.tar.gz rust-b3b7c2e97b8e34ebc2597c21653df4b2d7a37575.zip | |
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.
| -rw-r--r-- | src/libcore/str.rs | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 076eb8bbe6a..1ba958cd211 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1705,6 +1705,13 @@ pub trait StrSlice<'a> { fn utf16_units(&self) -> Utf16CodeUnits<'a>; } +#[inline(never)] +fn slice_error_fail(s: &str, begin: uint, end: uint) -> ! { + assert!(begin <= end); + fail!("index {} and/or {} in `{}` do not lie on character boundary", + begin, end, s); +} + impl<'a> StrSlice<'a> for &'a str { #[inline] fn contains<'a>(&self, needle: &'a str) -> bool { @@ -1808,22 +1815,34 @@ impl<'a> StrSlice<'a> for &'a str { #[inline] fn slice(&self, begin: uint, end: uint) -> &'a str { - assert!(self.is_char_boundary(begin) && self.is_char_boundary(end), - "index {} and/or {} in `{}` do not lie on character boundary", begin, - end, *self); - unsafe { raw::slice_bytes(*self, begin, end) } + // is_char_boundary checks that the index is in [0, .len()] + if begin <= end && + self.is_char_boundary(begin) && + self.is_char_boundary(end) { + unsafe { raw::slice_unchecked(*self, begin, end) } + } else { + slice_error_fail(*self, begin, end) + } } #[inline] fn slice_from(&self, begin: uint) -> &'a str { - self.slice(begin, self.len()) + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(begin) { + unsafe { raw::slice_unchecked(*self, begin, self.len()) } + } else { + slice_error_fail(*self, begin, self.len()) + } } #[inline] fn slice_to(&self, end: uint) -> &'a str { - assert!(self.is_char_boundary(end), "index {} in `{}` does not lie on \ - a character boundary", end, *self); - unsafe { raw::slice_bytes(*self, 0, end) } + // is_char_boundary checks that the index is in [0, .len()] + if self.is_char_boundary(end) { + unsafe { raw::slice_unchecked(*self, 0, end) } + } else { + slice_error_fail(*self, 0, end) + } } fn slice_chars(&self, begin: uint, end: uint) -> &'a str { @@ -1898,9 +1917,10 @@ impl<'a> StrSlice<'a> for &'a str { #[inline] fn is_char_boundary(&self, index: uint) -> bool { if index == self.len() { return true; } - if index > self.len() { return false; } - let b = self.as_bytes()[index]; - return b < 128u8 || b >= 192u8; + match self.as_bytes().get(index) { + None => false, + Some(&b) => b < 128u8 || b >= 192u8, + } } #[inline] |
