diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/buffer_queue.rs | 80 | ||||
-rw-r--r-- | src/util/smallcharset.rs | 4 |
2 files changed, 42 insertions, 42 deletions
diff --git a/src/util/buffer_queue.rs b/src/util/buffer_queue.rs index 7f8c3cc..5201a57 100644 --- a/src/util/buffer_queue.rs +++ b/src/util/buffer_queue.rs @@ -20,8 +20,6 @@ use std::collections::VecDeque; -use tendril::StrTendril; - pub use self::SetResult::{FromSet, NotFromSet}; use crate::util::smallcharset::SmallCharSet; @@ -35,7 +33,7 @@ pub enum SetResult { /// A character from the `SmallCharSet`. FromSet(char), /// A string buffer containing no characters from the `SmallCharSet`. - NotFromSet(StrTendril), + NotFromSet(String), } /// A queue of owned string buffers, which supports incrementally consuming characters. @@ -46,7 +44,7 @@ pub enum SetResult { #[derive(Debug)] pub struct BufferQueue { /// Buffers to process. - buffers: VecDeque<StrTendril>, + buffers: VecDeque<(usize, String)>, } impl BufferQueue { @@ -66,28 +64,32 @@ impl BufferQueue { /// Get the buffer at the beginning of the queue. #[inline] - pub fn pop_front(&mut self) -> Option<StrTendril> { - self.buffers.pop_front() + pub fn pop_front(&mut self) -> Option<String> { + if let Some((i, s)) = self.buffers.pop_front() { + return Some(s[i..].into()) + } + None + // self.buffers.pop_front().map(|(i, s)| &s[i..]) } /// Add a buffer to the beginning of the queue. /// /// If the buffer is empty, it will be skipped. - pub fn push_front(&mut self, buf: StrTendril) { - if buf.len32() == 0 { + pub fn push_front(&mut self, buf: String) { + if buf.len() == 0 { return; } - self.buffers.push_front(buf); + self.buffers.push_front((0, buf)); } /// Add a buffer to the end of the queue. /// /// If the buffer is empty, it will be skipped. - pub fn push_back(&mut self, buf: StrTendril) { - if buf.len32() == 0 { + pub fn push_back(&mut self, buf: String) { + if buf.len() == 0 { return; } - self.buffers.push_back(buf); + self.buffers.push_back((0, buf)); } /// Look at the next available character without removing it, if the queue is not empty. @@ -95,11 +97,11 @@ impl BufferQueue { debug_assert!( self.buffers .iter() - .find(|el| el.len32() == 0) + .find(|(i, s)| s[*i..].is_empty()) .is_none(), "invariant \"all buffers in the queue are non-empty\" failed" ); - self.buffers.front().map(|b| b.chars().next().unwrap()) + self.buffers.front().map(|(i, s)| s[*i..].chars().next().unwrap()) } /// Get the next character if one is available, removing it from the queue. @@ -108,9 +110,10 @@ impl BufferQueue { pub fn next(&mut self) -> Option<char> { let (result, now_empty) = match self.buffers.front_mut() { None => (None, false), - Some(buf) => { - let c = buf.pop_front_char().expect("empty buffer in queue"); - (Some(c), buf.is_empty()) + Some((i, buf)) => { + let c = &buf[*i..].chars().next().expect("empty buffer in queue"); + *i += c.len_utf8(); + (Some(*c), buf[*i..].is_empty()) }, }; @@ -126,18 +129,15 @@ impl BufferQueue { pub fn pop_except_from(&mut self, set: SmallCharSet) -> Option<SetResult> { let (result, now_empty) = match self.buffers.front_mut() { None => (None, false), - Some(buf) => { - let n = set.nonmember_prefix_len(&buf); + Some((i, buf)) => { + let n = set.nonmember_prefix_len(&buf[*i..]); if n > 0 { - let out; - unsafe { - out = buf.unsafe_subtendril(0, n); - buf.unsafe_pop_front(n); - } - (Some(NotFromSet(out)), buf.is_empty()) + let out = buf.drain(*i..*i + n).collect(); + (Some(NotFromSet(out)), buf[*i..].is_empty()) } else { - let c = buf.pop_front_char().expect("empty buffer in queue"); - (Some(FromSet(c)), buf.is_empty()) + let c = &buf[*i..].chars().next().expect("empty buffer in queue"); + *i += c.len_utf8(); + (Some(FromSet(*c)), buf[*i..].is_empty()) } }, }; @@ -166,9 +166,9 @@ impl BufferQueue { if buffers_exhausted >= self.buffers.len() { return None; } - let buf = &self.buffers[buffers_exhausted]; + let (i, buf) = &self.buffers[buffers_exhausted]; - if !eq(&buf.as_bytes()[consumed_from_last], &pattern_byte) { + if !eq(&buf[*i..].as_bytes()[consumed_from_last], &pattern_byte) { return Some(false); } @@ -186,7 +186,9 @@ impl BufferQueue { match self.buffers.front_mut() { None => assert_eq!(consumed_from_last, 0), - Some(ref mut buf) => buf.pop_front(consumed_from_last as u32), + Some((i, _buf)) => { + *i += consumed_from_last; + }, } Some(true) @@ -196,8 +198,6 @@ impl BufferQueue { #[cfg(test)] #[allow(non_snake_case)] mod test { - use tendril::SliceExt; - use super::BufferQueue; use super::SetResult::{FromSet, NotFromSet}; @@ -207,7 +207,7 @@ mod test { assert_eq!(bq.peek(), None); assert_eq!(bq.next(), None); - bq.push_back("abc".to_tendril()); + bq.push_back("abc".into()); assert_eq!(bq.peek(), Some('a')); assert_eq!(bq.next(), Some('a')); assert_eq!(bq.peek(), Some('b')); @@ -222,10 +222,10 @@ mod test { #[test] fn can_unconsume() { let mut bq = BufferQueue::new(); - bq.push_back("abc".to_tendril()); + bq.push_back("abc".into()); assert_eq!(bq.next(), Some('a')); - bq.push_front("xy".to_tendril()); + bq.push_front("xy".into()); assert_eq!(bq.next(), Some('x')); assert_eq!(bq.next(), Some('y')); assert_eq!(bq.next(), Some('b')); @@ -236,11 +236,11 @@ mod test { #[test] fn can_pop_except_set() { let mut bq = BufferQueue::new(); - bq.push_back("abc&def".to_tendril()); + bq.push_back("abc&def".into()); let mut pop = || bq.pop_except_from(small_char_set!('&')); - assert_eq!(pop(), Some(NotFromSet("abc".to_tendril()))); + assert_eq!(pop(), Some(NotFromSet("abc".into()))); assert_eq!(pop(), Some(FromSet('&'))); - assert_eq!(pop(), Some(NotFromSet("def".to_tendril()))); + assert_eq!(pop(), Some(NotFromSet("def".into()))); assert_eq!(pop(), None); } @@ -250,8 +250,8 @@ mod test { // integration tests for more thorough testing with many // different input buffer splits. let mut bq = BufferQueue::new(); - bq.push_back("a".to_tendril()); - bq.push_back("bc".to_tendril()); + bq.push_back("a".into()); + bq.push_back("bc".into()); assert_eq!(bq.eat("abcd", u8::eq_ignore_ascii_case), None); assert_eq!(bq.eat("ax", u8::eq_ignore_ascii_case), Some(false)); assert_eq!(bq.eat("ab", u8::eq_ignore_ascii_case), Some(true)); diff --git a/src/util/smallcharset.rs b/src/util/smallcharset.rs index aeeb189..2bf8585 100644 --- a/src/util/smallcharset.rs +++ b/src/util/smallcharset.rs @@ -41,7 +41,7 @@ impl SmallCharSet { /// Count the number of bytes of characters at the beginning of `buf` which are not in the set. /// /// This functionality is used in [`BufferQueue::pop_except_from`]. - pub fn nonmember_prefix_len(&self, buf: &str) -> u32 { + pub fn nonmember_prefix_len(&self, buf: &str) -> usize { let mut n = 0; for b in buf.bytes() { if b >= 64 || !self.contains(b) { @@ -61,7 +61,7 @@ mod test { #[test] fn nonmember_prefix() { for &c in ['&', '\0'].iter() { - for x in 0..48u32 { + for x in 0..48 { for y in 0..48u32 { let mut s = repeat("x").take(x as usize).collect::<String>(); s.push(c); |