pub struct Bytes<'a> {
start: *const u8,
end: *const u8,
cursor: *const u8,
phantom: core::marker::PhantomData<&'a ()>,
}
#[allow(missing_docs)]
impl<'a> Bytes<'a> {
#[inline]
#[must_use]
pub fn new(slice: &'a [u8]) -> Bytes<'a> {
let start = slice.as_ptr();
let end = unsafe { start.add(slice.len()) };
let cursor = start;
Bytes {
start,
end,
cursor,
phantom: core::marker::PhantomData,
}
}
#[inline]
#[must_use]
pub fn pos(&self) -> usize {
self.cursor as usize - self.start as usize
}
#[inline]
#[must_use]
pub fn peek(&self) -> Option<u8> {
if self.cursor < self.end {
Some(unsafe { *self.cursor })
} else {
None
}
}
#[inline]
#[must_use]
pub fn peek_ahead(&self, n: usize) -> Option<u8> {
let ptr = self.cursor.wrapping_add(n);
if ptr < self.end {
Some(unsafe { *ptr })
} else {
None
}
}
#[inline]
#[must_use]
pub fn peek_n<'b: 'a, U: TryFrom<&'a [u8]>>(&'b self, n: usize) -> Option<U> {
self.as_ref().get(..n)?.try_into().ok()
}
#[inline]
pub unsafe fn bump(&mut self) {
self.advance(1);
}
#[inline]
pub unsafe fn advance(&mut self, n: usize) {
self.cursor = self.cursor.add(n);
debug_assert!(self.cursor <= self.end, "overflow");
}
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.end as usize - self.cursor as usize
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn slice(&mut self) -> &'a [u8] {
let slice = unsafe { slice_from_ptr_range(self.start, self.cursor) };
self.commit();
slice
}
#[inline]
pub unsafe fn slice_skip(&mut self, skip: usize) -> &'a [u8] {
debug_assert!(skip <= self.cursor.offset_from(self.start).cast_unsigned());
let head = slice_from_ptr_range(self.start, self.cursor.sub(skip));
self.commit();
head
}
#[inline]
pub fn commit(&mut self) {
self.start = self.cursor;
}
#[inline]
pub unsafe fn advance_and_commit(&mut self, n: usize) {
self.advance(n);
self.commit();
}
#[inline]
#[must_use]
pub fn as_ptr(&self) -> *const u8 {
self.cursor
}
#[inline]
#[must_use]
pub fn start(&self) -> *const u8 {
self.start
}
#[inline]
#[must_use]
pub fn end(&self) -> *const u8 {
self.end
}
#[inline]
pub unsafe fn set_cursor(&mut self, ptr: *const u8) {
debug_assert!(ptr >= self.start);
debug_assert!(ptr <= self.end);
self.cursor = ptr;
}
}
impl AsRef<[u8]> for Bytes<'_> {
#[inline]
fn as_ref(&self) -> &[u8] {
unsafe { slice_from_ptr_range(self.cursor, self.end) }
}
}
#[inline]
unsafe fn slice_from_ptr_range<'a>(start: *const u8, end: *const u8) -> &'a [u8] {
debug_assert!(start <= end);
core::slice::from_raw_parts(start, end as usize - start as usize)
}
impl Iterator for Bytes<'_> {
type Item = u8;
#[inline]
fn next(&mut self) -> Option<u8> {
if self.cursor < self.end {
unsafe {
let b = *self.cursor;
self.bump();
Some(b)
}
} else {
None
}
}
}
#[derive(Clone, Debug)]
pub struct BytesPointer<'a> {
content: &'a [u8],
pos: usize,
peek_pos: usize,
}
impl<'a> BytesPointer<'a> {
#[must_use]
pub fn new(content: &'a [u8]) -> Self {
Self {
content,
pos: 0,
peek_pos: 0,
}
}
#[inline]
#[must_use]
pub fn content(&self) -> &'a [u8] {
self.content
}
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.content.is_empty()
}
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.content.len()
}
#[inline]
#[must_use]
pub fn distance(&self) -> usize {
self.peek_pos - self.pos
}
#[inline]
#[must_use]
pub fn peek_rem_len(&self) -> usize {
(self.content[self.peek_pos..]).len()
}
#[inline]
#[must_use]
pub fn rem_len(&self) -> usize {
(self.content[self.pos..]).len()
}
#[inline]
pub fn reset(&mut self) {
self.reset_to(0);
}
#[inline]
pub fn reset_to(&mut self, to: usize) {
self.pos = to;
self.peek_pos = to;
}
#[inline]
pub fn skip_position(&mut self) -> usize {
let diff = self.peek_pos - self.pos;
self.pos = self.peek_pos;
diff
}
#[inline]
pub fn skip(&mut self) {
self.pos = self.peek_pos;
}
#[inline]
pub fn peek(&mut self, by: usize) -> Option<&'a [u8]> {
self.peek_slice(by)
}
#[inline]
pub fn peek_next(&mut self) -> Option<&'a [u8]> {
if let Some(res) = self.peek_slice(1) {
self.peek_pos += 1;
return Some(res);
}
None
}
#[inline]
pub fn peek_next_by(&mut self, by: usize) -> Option<&'a [u8]> {
if let Some(res) = self.peek_slice(by) {
self.peek_pos += by;
return Some(res);
}
None
}
#[inline]
pub fn unpeek_next(&mut self) -> Option<&'a [u8]> {
if let Some(res) = self.unpeek_slice(1) {
return Some(res);
}
None
}
#[inline]
fn unpeek_slice(&mut self, by: usize) -> Option<&'a [u8]> {
if self.peek_pos == 0 {
return None;
}
if self.peek_pos > self.pos {
self.peek_pos -= 1;
}
let new_peek_pos = self.peek_pos + by;
Some(&self.content[self.peek_pos..new_peek_pos])
}
#[inline]
pub fn scan_remaining(&mut self) -> Option<&'a [u8]> {
Some(&self.content[self.pos..])
}
#[inline]
pub fn scan(&mut self) -> Option<&'a [u8]> {
Some(&self.content[self.pos..self.peek_pos])
}
#[cfg_attr(feature = "trace_block", tracing::instrument(level = "trace"))]
#[inline]
pub fn ppeek_at(&mut self, from: usize, to: usize) -> Option<&'a [u8]> {
let new_peek_pos = self.pos + from;
let until_pos = if new_peek_pos + to > self.content.len() {
self.content.len()
} else {
new_peek_pos + to
};
if new_peek_pos > self.content.len() {
return None;
}
Some(&self.content[new_peek_pos..until_pos])
}
#[cfg_attr(feature = "trace_block", tracing::instrument(level = "trace"))]
#[inline]
pub fn vpeek_at(&mut self, from: usize, to: usize) -> Option<&'a [u8]> {
let new_peek_pos = self.peek_pos + from;
let until_pos = if new_peek_pos + to > self.content.len() {
self.content.len()
} else {
new_peek_pos + to
};
if new_peek_pos > self.content.len() {
return None;
}
Some(&self.content[new_peek_pos..until_pos])
}
#[cfg_attr(feature = "trace_block", tracing::instrument(level = "trace"))]
#[inline]
fn peek_slice(&mut self, by: usize) -> Option<&'a [u8]> {
if self.peek_pos + by > self.content.len() {
return None;
}
let from = self.peek_pos;
let until_pos = self.peek_pos + by;
Some(&self.content[from..until_pos])
}
#[cfg_attr(feature = "trace_block", tracing::instrument(level = "trace"))]
#[inline]
pub fn take_with_amount(&mut self, by: usize) -> Option<(&'a [u8], (usize, usize))> {
if self.peek_pos + by > self.content.len() {
return None;
}
let until_pos = if self.peek_pos + by > self.content.len() {
self.content.len()
} else {
self.peek_pos + by
};
if self.pos >= self.content.len() {
return None;
}
let from = self.pos;
let position = (from, until_pos);
let content_slice = &self.content[from..until_pos];
let res = Some((content_slice, position));
self.pos = self.peek_pos;
res
}
#[inline]
pub fn take_positional(&mut self) -> Option<(&'a [u8], (usize, usize))> {
self.take_with_amount(0)
}
#[inline]
pub fn take(&mut self) -> Option<&'a [u8]> {
match self.take_with_amount(0) {
Some((text, _)) => Some(text),
None => None,
}
}
}