use crate::util::buffer::content_len_raw;
pub const N: u8 = b'\n';
pub const R: u8 = b'\r';
pub const S: u8 = b' ';
#[inline]
#[must_use]
pub const fn is_whitespace(c: u8) -> bool { is_newline(c) || is_space(c) }
#[inline]
#[must_use]
pub const fn is_space(c: u8) -> bool { c == S }
#[inline]
#[must_use]
pub const fn is_newline(c: u8) -> bool { c == N || c == R }
pub fn find_char<P>(buffer: &[u8], start: usize, is_target: P) -> Option<usize>
where
P: Fn(u8) -> bool,
{
let mut newline = start;
loop {
if newline >= buffer.len() {
return None;
}
let char_at = buffer[newline];
if is_target(char_at) {
return Some(newline);
} else if char_at == 0 {
return None;
} else {
newline += 1;
}
}
}
pub struct ByteLines<'a> {
buffer: &'a [u8],
position: usize,
done: bool,
}
impl<'a> ByteLines<'a> {
#[must_use]
pub const fn new(buffer: &'a [u8]) -> Self {
ByteLines {
buffer,
position: 0,
done: false,
}
}
}
impl<'a> Iterator for ByteLines<'a> {
type Item = (&'a [u8], usize);
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
match find_char(self.buffer, self.position, is_newline) {
Some(pos) => {
let result = Some((&self.buffer[self.position..pos], self.position));
self.position = pos + 1;
result
},
None => {
self.done = true;
let remaining_len = content_len_raw(&self.buffer[self.position..]);
if remaining_len > 0 {
Some((
&self.buffer[self.position..(self.position + remaining_len)],
self.position,
))
} else {
None
}
},
}
}
}