use alloc::sync::Arc;
use deser_core::de::{self, Deserialize, DeserializeDriver, LexicalRules, deserialize_value};
use deser_core::{Error, ErrorKind, Source, TrackLocations};
use crate::common::{Borrowing, Copying, Out, decode_utf16_text, syntax_error};
use crate::format::Format;
use crate::{read_ascii, read_binary, read_xml};
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct DeserializerConfig {
context: deser_core::Context,
}
impl DeserializerConfig {
pub const fn new() -> DeserializerConfig {
DeserializerConfig {
context: deser_core::Context::new(),
}
}
pub const fn builder() -> DeserializerConfigBuilder {
DeserializerConfigBuilder::new()
}
pub const fn into_builder(self) -> DeserializerConfigBuilder {
DeserializerConfigBuilder { value: self }
}
pub fn set_context(&mut self, context: deser_core::Context) {
self.context = context;
}
pub(crate) fn without_context(&self) -> DeserializerConfig {
let mut config = self.clone();
config.context = deser_core::Context::default();
config
}
pub fn context(&self) -> &deser_core::Context {
&self.context
}
pub fn from_slice<'de, T: Deserialize<'de>>(&self, input: &'de [u8]) -> Result<T, Error> {
deserialize_value(|driver| self.drive_slice(input, driver))
}
fn drive_slice<'de>(
&self,
input: &'de [u8],
driver: &mut DeserializeDriver<'_, 'de>,
) -> Result<(), Error> {
de::Deserializer::drive(
&mut Deserializer::from_slice_with_config(input, self.clone()),
driver,
)
}
}
#[derive(Debug, Clone)]
#[must_use]
pub struct DeserializerConfigBuilder {
value: DeserializerConfig,
}
impl DeserializerConfigBuilder {
pub const fn new() -> DeserializerConfigBuilder {
DeserializerConfigBuilder {
value: DeserializerConfig::new(),
}
}
pub fn context(mut self, context: deser_core::Context) -> DeserializerConfigBuilder {
self.value.set_context(context);
self
}
pub const fn build(self) -> DeserializerConfig {
let value = unsafe { core::ptr::read(&self.value) };
core::mem::forget(self);
value
}
}
impl Default for DeserializerConfigBuilder {
fn default() -> DeserializerConfigBuilder {
DeserializerConfigBuilder::new()
}
}
pub struct Deserializer<'a> {
input: &'a [u8],
format: Format,
config: DeserializerConfig,
}
impl<'a> Deserializer<'a> {
pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> {
Deserializer::from_slice_with_config(input, DeserializerConfig::new())
}
pub fn from_slice_with_config(input: &'a [u8], config: DeserializerConfig) -> Deserializer<'a> {
Deserializer {
input,
format: Format::detect(input),
config,
}
}
pub fn config(&self) -> &DeserializerConfig {
&self.config
}
pub fn format(&self) -> Format {
self.format
}
pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
de::Deserializer::deserialize(self)
}
pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error>
where
T: Deserialize<'a>,
F: FnOnce(&mut DeserializeDriver<'_, 'a>),
{
de::Deserializer::deserialize_with(self, setup)
}
pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
if !self.config.context.is_empty() {
driver.set_default_context(self.config.context.clone());
}
if self.format == Format::Binary {
return read_binary::parse(self.input, &mut Borrowing(driver));
}
if let Some(text) = decode_utf16_text(self.input) {
let text = text.map_err(|offset| syntax_error(offset, "invalid UTF-16"))?;
let text = text.strip_prefix('\u{feff}').unwrap_or(&text);
return self.drive_text(text, &mut Copying(driver));
}
let input = self
.input
.strip_prefix(b"\xef\xbb\xbf")
.unwrap_or(self.input);
let text = core::str::from_utf8(input).map_err(|err| {
let offset = self.input.len() - input.len() + err.valid_up_to();
Error::with_offset(ErrorKind::Syntax, "invalid UTF-8", offset)
})?;
self.drive_text(text, &mut Borrowing(driver))
}
fn drive_text<'i, O: Out<'i>>(&self, text: &'i str, out: &mut O) -> Result<(), Error> {
if TrackLocations::of(out.state_mut()) {
Source(Arc::<str>::from(text)).set(out.state_mut());
}
let rv = if self.format == Format::Xml {
read_xml::parse(text, out)
} else {
let mut rules = LexicalRules::STRICT;
rules.set_lenient_bools(true);
rules.set_default(out.state_mut());
read_ascii::parse(text, out)
};
rv.map_err(|mut err| {
err.resolve_position(text.as_bytes());
err
})
}
}
impl<'a> de::Deserializer<'a> for Deserializer<'a> {
fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
Deserializer::drive(self, driver)
}
}
pub fn from_slice<'de, T: Deserialize<'de>>(input: &'de [u8]) -> Result<T, Error> {
DeserializerConfig::new().from_slice(input)
}