aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/buffer_queue.rs80
-rw-r--r--src/util/smallcharset.rs4
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);