@@ -27,7 +27,7 @@ use iterator::{Iterator, FromIterator, Extendable};
27
27
use iterator:: { Filter , AdditiveIterator , Map } ;
28
28
use iterator:: { Invert , DoubleEndedIterator } ;
29
29
use libc;
30
- use num:: Zero ;
30
+ use num:: { Saturating , Zero } ;
31
31
use option:: { None , Option , Some } ;
32
32
use ptr;
33
33
use ptr:: RawPtr ;
@@ -1698,21 +1698,29 @@ impl<'self> StrSlice<'self> for &'self str {
1698
1698
fn char_range_at_reverse(&self, start: uint) -> CharRange {
1699
1699
let mut prev = start;
1700
1700
1701
- // while there is a previous byte == 10......
1702
- while prev > 0u && self[prev - 1u] & 192u8 == TAG_CONT_U8 {
1703
- prev -= 1u;
1704
- }
1701
+ prev = prev.saturating_sub(1);
1702
+ if self[prev] < 128 { return CharRange{ch: self[prev] as char, next: prev} }
1705
1703
1706
- // now refer to the initial byte of previous char
1707
- if prev > 0u {
1708
- prev -= 1u;
1709
- } else {
1710
- prev = 0u;
1711
- }
1704
+ // Multibyte case is a fn to allow char_range_at_reverse to inline cleanly
1705
+ fn multibyte_char_range_at_rev(s: &str, mut i: uint) -> CharRange {
1706
+ // while there is a previous byte == 10......
1707
+ while i > 0 && s[i] & 192u8 == TAG_CONT_U8 {
1708
+ i -= 1u;
1709
+ }
1710
+
1711
+ let mut val = s[i] as uint;
1712
+ let w = UTF8_CHAR_WIDTH[val] as uint;
1713
+ assert!((w != 0));
1712
1714
1715
+ val = utf8_first_byte!(val, w);
1716
+ val = utf8_acc_cont_byte!(val, s[i + 1]);
1717
+ if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); }
1718
+ if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); }
1719
+
1720
+ return CharRange {ch: val as char, next: i};
1721
+ }
1713
1722
1714
- let ch = self.char_at(prev);
1715
- return CharRange {ch:ch, next:prev};
1723
+ return multibyte_char_range_at_rev(*self, prev);
1716
1724
}
1717
1725
1718
1726
/// Plucks the character ending at the `i`th byte of a string
0 commit comments