use super::*;
use crate::{debug, query::JsonString, result::InputRecorder};
pub struct BorrowedBytes<'a> {
bytes: &'a [u8],
last_block: LastBlock,
}
pub struct BorrowedBytesBlockIterator<'a, 'r, const N: usize, R> {
input: &'a [u8],
last_block: &'a LastBlock,
idx: usize,
recorder: &'r R,
}
impl<'a> BorrowedBytes<'a> {
#[must_use]
#[inline(always)]
pub unsafe fn new(bytes: &'a [u8]) -> Self {
assert_eq!(bytes.len() % MAX_BLOCK_SIZE, 0);
let last_block = in_slice::pad_last_block(bytes);
Self { bytes, last_block }
}
#[must_use]
#[inline(always)]
pub fn as_slice(&self) -> &[u8] {
self.bytes
}
#[must_use]
#[inline(always)]
pub fn to_owned(&self) -> OwnedBytes {
OwnedBytes::from(self)
}
}
impl<'a> AsRef<[u8]> for BorrowedBytes<'a> {
#[inline(always)]
fn as_ref(&self) -> &[u8] {
self.bytes
}
}
impl<'a, 'r, const N: usize, R> BorrowedBytesBlockIterator<'a, 'r, N, R>
where
R: InputRecorder<&'a [u8]>,
{
#[must_use]
#[inline(always)]
pub(super) fn new(bytes: &'a [u8], last_block: &'a LastBlock, recorder: &'r R) -> Self {
Self {
input: bytes,
idx: 0,
last_block,
recorder,
}
}
}
impl<'a> Input for BorrowedBytes<'a> {
type BlockIterator<'b, 'r, const N: usize, R> = BorrowedBytesBlockIterator<'b, 'r, N, R>
where Self: 'b,
R: InputRecorder<&'b [u8]> + 'r;
type Block<'b, const N: usize> = &'b [u8] where Self: 'b;
#[inline(always)]
fn len_hint(&self) -> Option<usize> {
Some((self.bytes.len() / MAX_BLOCK_SIZE + 1) * MAX_BLOCK_SIZE)
}
#[inline(always)]
fn iter_blocks<'b, 'r, R, const N: usize>(&'b self, recorder: &'r R) -> Self::BlockIterator<'b, 'r, N, R>
where
R: InputRecorder<&'b [u8]>,
{
Self::BlockIterator {
input: self.bytes,
idx: 0,
last_block: &self.last_block,
recorder,
}
}
#[inline]
fn seek_backward(&self, from: usize, needle: u8) -> Option<usize> {
in_slice::seek_backward(self.bytes, from, needle)
}
#[inline]
fn seek_forward<const N: usize>(&self, from: usize, needles: [u8; N]) -> Result<Option<(usize, u8)>, InputError> {
Ok(in_slice::seek_forward(self.as_slice(), from, needles))
}
#[inline]
fn seek_non_whitespace_forward(&self, from: usize) -> Result<Option<(usize, u8)>, InputError> {
Ok(in_slice::seek_non_whitespace_forward(self.bytes, from))
}
#[inline]
fn seek_non_whitespace_backward(&self, from: usize) -> Option<(usize, u8)> {
in_slice::seek_non_whitespace_backward(self.bytes, from)
}
#[inline]
fn is_member_match(&self, from: usize, to: usize, member: &JsonString) -> bool {
in_slice::is_member_match(self.bytes, from, to, member)
}
}
impl<'a, 'r, const N: usize, R> FallibleIterator for BorrowedBytesBlockIterator<'a, 'r, N, R>
where
R: InputRecorder<&'a [u8]>,
{
type Item = &'a [u8];
type Error = InputError;
#[inline]
fn next(&mut self) -> Result<Option<Self::Item>, Self::Error> {
debug!("next!");
if self.idx >= self.input.len() {
Ok(None)
} else if self.idx >= self.last_block.absolute_start {
let i = self.idx - self.last_block.absolute_start;
self.idx += N;
let block = &self.last_block.bytes[i..i + N];
self.recorder.record_block_start(block);
Ok(Some(block))
} else {
let block = &self.input[self.idx..self.idx + N];
self.idx += N;
self.recorder.record_block_start(block);
Ok(Some(block))
}
}
}
impl<'a, 'r, const N: usize, R> InputBlockIterator<'a, N> for BorrowedBytesBlockIterator<'a, 'r, N, R>
where
R: InputRecorder<&'a [u8]> + 'r,
{
type Block = &'a [u8];
#[inline(always)]
fn offset(&mut self, count: isize) {
assert!(count >= 0);
debug!("offsetting input iter by {count}");
self.idx += count as usize * N;
}
#[inline(always)]
fn get_offset(&self) -> usize {
debug!("getting input iter {}", self.idx);
self.idx
}
}