properly iterate through UTF-8 strings (#350)

This commit is contained in:
Mark Thom
2020-04-14 23:14:47 -06:00
parent f6c995157e
commit c9074d8d96

View File

@@ -48,13 +48,15 @@ fn scan_for_terminator<Iter: Iterator<Item = char>>(iter: Iter) -> usize {
pub struct PStrIter { pub struct PStrIter {
buf: *const u8, buf: *const u8,
len: usize,
} }
impl PStrIter { impl PStrIter {
#[inline] #[inline]
fn from(buf: *const u8, idx: usize) -> Self { fn from(buf: *const u8, len: usize, idx: usize) -> Self {
PStrIter { PStrIter {
buf: (buf as usize + idx) as *const _ buf: (buf as usize + idx) as *const _,
len: len - idx,
} }
} }
} }
@@ -64,27 +66,13 @@ impl Iterator for PStrIter {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
unsafe { unsafe {
let mut byte_count = 0; let slice = slice::from_raw_parts(self.buf, self.len);
for n in 0 .. mem::size_of::<char>() {
let b = ptr::read((self.buf as usize + n) as *const u8);
if b == 0u8 {
break;
} else {
byte_count += 1;
}
}
if byte_count == 0 {
return None;
}
let slice = slice::from_raw_parts(self.buf, byte_count);
let s = str::from_utf8(slice).unwrap(); let s = str::from_utf8(slice).unwrap();
if let Some(c) = s.chars().next() { if let Some(c) = s.chars().next() {
self.buf = self.buf.offset(c.len_utf8() as isize); self.buf = self.buf.offset(c.len_utf8() as isize);
self.len -= c.len_utf8();
Some(c) Some(c)
} else { } else {
None None
@@ -212,7 +200,7 @@ impl PartialString {
#[inline] #[inline]
pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter { pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
PStrIter::from(self.buf, index.start) PStrIter::from(self.buf, self.len, index.start)
} }
#[inline] #[inline]