use crate::copy_on_escape::CopyOnEscape;
use crate::escape_processor::{self, UnicodeEscapeCollector};
use crate::event_processor::ContentExtractor;
use crate::shared::{ContentRange, DataSource, State};
use crate::slice_input_buffer::{InputBuffer, SliceInputBuffer};
use crate::{Event, JsonNumber, ParseError};
pub struct SliceContentBuilder<'a, 'b> {
buffer: SliceInputBuffer<'a>,
copy_on_escape: CopyOnEscape<'a, 'b>,
parser_state: State,
unicode_escape_collector: UnicodeEscapeCollector,
}
impl<'a, 'b> SliceContentBuilder<'a, 'b> {
pub fn new(input: &'a [u8], scratch_buffer: &'b mut [u8]) -> Self {
Self {
buffer: SliceInputBuffer::new(input),
copy_on_escape: CopyOnEscape::new(input, scratch_buffer),
parser_state: State::None,
unicode_escape_collector: UnicodeEscapeCollector::new(),
}
}
pub fn buffer(&self) -> &SliceInputBuffer<'a> {
&self.buffer
}
pub fn buffer_mut(&mut self) -> &mut SliceInputBuffer<'a> {
&mut self.buffer
}
}
impl ContentExtractor for SliceContentBuilder<'_, '_> {
fn next_byte(&mut self) -> Result<Option<u8>, ParseError> {
match self.buffer_mut().consume_byte() {
Ok(byte) => Ok(Some(byte)),
Err(crate::slice_input_buffer::Error::ReachedEnd) => Ok(None),
Err(err) => Err(err.into()),
}
}
fn parser_state_mut(&mut self) -> &mut State {
&mut self.parser_state
}
fn parser_state(&self) -> &State {
&self.parser_state
}
fn unicode_escape_collector_mut(&mut self) -> &mut UnicodeEscapeCollector {
&mut self.unicode_escape_collector
}
fn current_position(&self) -> usize {
self.buffer.current_pos()
}
fn begin_string_content(&mut self, pos: usize) {
self.copy_on_escape.begin_string(pos);
}
fn extract_string_content(&mut self, start_pos: usize) -> Result<Event<'_, '_>, ParseError> {
let current_pos = self.current_position();
if self.has_unescaped_content() {
let end_pos = ContentRange::end_position_excluding_delimiter(current_pos);
self.copy_on_escape.end_string(end_pos)?; }
let content_piece = crate::shared::get_content_piece(self, start_pos, current_pos)?;
Ok(Event::String(content_piece.into_string()?))
}
fn extract_key_content(&mut self, start_pos: usize) -> Result<Event<'_, '_>, ParseError> {
let current_pos = self.current_position();
if self.has_unescaped_content() {
let end_pos = ContentRange::end_position_excluding_delimiter(current_pos);
self.copy_on_escape.end_string(end_pos)?; }
let content_piece = crate::shared::get_content_piece(self, start_pos, current_pos)?;
Ok(Event::Key(content_piece.into_string()?))
}
fn extract_number(
&mut self,
start_pos: usize,
_from_container_end: bool,
_finished: bool,
) -> Result<Event<'_, '_>, ParseError> {
let end_pos = ContentRange::end_position_excluding_delimiter(self.current_position());
let number_bytes = self.get_borrowed_slice(start_pos, end_pos)?;
let json_number = JsonNumber::from_slice(number_bytes)?;
Ok(Event::Number(json_number))
}
fn begin_escape_sequence(&mut self) -> Result<(), ParseError> {
Ok(())
}
fn begin_unicode_escape(&mut self) -> Result<(), ParseError> {
Ok(())
}
fn handle_simple_escape_char(&mut self, escape_char: u8) -> Result<(), ParseError> {
self.copy_on_escape
.handle_escape(self.buffer.current_pos(), escape_char)?;
Ok(())
}
fn process_unicode_escape_with_collector(&mut self) -> Result<(), ParseError> {
let current_pos = self.buffer.current_pos();
let had_pending_high_surrogate = self.unicode_escape_collector.has_pending_high_surrogate();
let pending_surrogate = self.unicode_escape_collector.get_pending_high_surrogate();
let (utf8_bytes_result, escape_start_pos, new_pending_surrogate) =
escape_processor::process_unicode_escape_sequence(
current_pos,
pending_surrogate,
self, )?;
self.unicode_escape_collector
.set_pending_high_surrogate(new_pending_surrogate);
if let Some((utf8_bytes, len)) = utf8_bytes_result {
let safe_len = len.min(utf8_bytes.len()).min(4);
let utf8_slice = &utf8_bytes[..safe_len];
if had_pending_high_surrogate {
self.copy_on_escape
.handle_unicode_escape(escape_start_pos, &[])?;
let low_surrogate_pos = escape_start_pos
.checked_add(6)
.ok_or(ParseError::NumericOverflow)?;
self.copy_on_escape
.handle_unicode_escape(low_surrogate_pos, utf8_slice)?;
} else {
self.copy_on_escape
.handle_unicode_escape(escape_start_pos, utf8_slice)?;
}
}
Ok(())
}
}
impl<'a, 'b> DataSource<'a, 'b> for SliceContentBuilder<'a, 'b> {
fn get_borrowed_slice(&'a self, start: usize, end: usize) -> Result<&'a [u8], ParseError> {
self.buffer.slice(start, end).map_err(Into::into)
}
fn get_unescaped_slice(&'b self) -> Result<&'b [u8], ParseError> {
if !self.copy_on_escape.has_unescaped_content() {
return Err(ParseError::Unexpected(
crate::shared::UnexpectedState::StateMismatch,
));
}
self.copy_on_escape.get_scratch_contents()
}
fn has_unescaped_content(&self) -> bool {
self.copy_on_escape.has_unescaped_content()
}
}