use core::marker::PhantomData;
use deser_core::Error;
use deser_core::de::{self, Deserialize, DeserializeDriver, deserialize_value};
use crate::parser::{Borrowing, Parser, Progress, syntax_error};
#[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> {
let mut deserializer = Deserializer::from_slice_with_config(input, self.clone());
de::Deserializer::drive(&mut deserializer, driver)?;
deserializer.end()
}
}
#[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],
pos: usize,
config: DeserializerConfig,
parser: Parser,
}
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,
pos: 0,
config,
parser: Parser::default(),
}
}
pub fn config(&self) -> &DeserializerConfig {
&self.config
}
pub fn offset(&self) -> usize {
self.pos
}
pub fn is_end(&self) -> bool {
self.pos >= self.input.len()
}
pub fn end(&self) -> Result<(), Error> {
if self.is_end() {
Ok(())
} else {
Err(syntax_error(self.pos, "trailing data after item"))
}
}
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 iter<T: Deserialize<'a>>(&mut self) -> Iter<'_, 'a, T> {
Iter {
de: self,
failed: false,
_marker: PhantomData,
}
}
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());
}
match self
.parser
.parse(self.input, self.pos, true, 0, &mut Borrowing(driver))
{
Ok(Progress::Done(pos)) => {
self.pos = pos;
Ok(())
}
Ok(Progress::NeedMore(_)) => unreachable!("the input is complete"),
Err(err) => {
self.pos = self.parser.position();
self.parser.reset();
Err(err)
}
}
}
}
pub struct Iter<'b, 'a, T> {
de: &'b mut Deserializer<'a>,
failed: bool,
_marker: PhantomData<fn() -> T>,
}
impl<'b, 'a, T: Deserialize<'a>> Iterator for Iter<'b, 'a, T> {
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.failed || self.de.is_end() {
return None;
}
let rv = self.de.deserialize();
self.failed = rv.is_err();
Some(rv)
}
}
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)
}