use std::{borrow::Borrow, io::Read};
use serde::de::{DeserializeSeed, MapAccess, SeqAccess};
use super::{Config, SchemaAwareDeserializer};
use crate::schema::MapSchema;
use crate::{Error, Schema, schema::ArraySchema, util::zag_i64};
pub struct BlockDeserializer<'s, 'r, R: Read, S: Borrow<Schema>> {
reader: &'r mut R,
schema: &'s Schema,
config: Config<'s, S>,
remaining: Option<u64>,
}
impl<'s, 'r, R: Read, S: Borrow<Schema>> BlockDeserializer<'s, 'r, R, S> {
pub fn array(
reader: &'r mut R,
schema: &'s ArraySchema,
config: Config<'s, S>,
) -> Result<Self, Error> {
let schema = if let Schema::Ref { name } = schema.items.as_ref() {
config.get_schema(name)?
} else {
&schema.items
};
let remaining = Self::read_block_header(reader)?;
Ok(Self {
reader,
schema,
config,
remaining,
})
}
pub fn map(
reader: &'r mut R,
schema: &'s MapSchema,
config: Config<'s, S>,
) -> Result<Self, Error> {
let schema = if let Schema::Ref { name } = schema.types.as_ref() {
config.get_schema(name)?
} else {
&schema.types
};
let remaining = Self::read_block_header(reader)?;
Ok(Self {
reader,
schema,
config,
remaining,
})
}
fn read_block_header(reader: &mut R) -> Result<Option<u64>, Error> {
let remaining = zag_i64(reader)?;
if remaining < 0 {
let _bytes = zag_i64(reader)?;
}
if remaining == 0 {
Ok(None)
} else {
Ok(Some(remaining.unsigned_abs()))
}
}
}
impl<'de, 's, 'r, R: Read, S: Borrow<Schema>> SeqAccess<'de> for BlockDeserializer<'s, 'r, R, S> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: DeserializeSeed<'de>,
{
if let Some(mut remaining) = self.remaining {
let value = seed.deserialize(SchemaAwareDeserializer::new(
self.reader,
self.schema,
self.config,
)?)?;
remaining -= 1;
if remaining == 0 {
self.remaining = Self::read_block_header(self.reader)?;
} else {
self.remaining = Some(remaining);
}
Ok(Some(value))
} else {
Ok(None)
}
}
fn size_hint(&self) -> Option<usize> {
self.remaining
.map(|x| usize::try_from(x).unwrap_or(usize::MAX))
}
}
impl<'de, 's, 'r, R: Read, S: Borrow<Schema>> MapAccess<'de> for BlockDeserializer<'s, 'r, R, S> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: DeserializeSeed<'de>,
{
if self.remaining.is_some() {
seed.deserialize(SchemaAwareDeserializer::new(
self.reader,
&Schema::String,
self.config,
)?)
.map(Some)
} else {
Ok(None)
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: DeserializeSeed<'de>,
{
let mut remaining = self
.remaining
.expect("next_key returned None, next_value should not have been called");
let value = seed.deserialize(SchemaAwareDeserializer::new(
self.reader,
self.schema,
self.config,
)?)?;
remaining -= 1;
if remaining == 0 {
self.remaining = Self::read_block_header(self.reader)?;
} else {
self.remaining = Some(remaining);
}
Ok(value)
}
fn next_entry_seed<K, V>(
&mut self,
kseed: K,
vseed: V,
) -> Result<Option<(K::Value, V::Value)>, Self::Error>
where
K: DeserializeSeed<'de>,
V: DeserializeSeed<'de>,
{
if let Some(mut remaining) = self.remaining {
let key = kseed.deserialize(SchemaAwareDeserializer::new(
self.reader,
&Schema::String,
self.config,
)?)?;
let value = vseed.deserialize(SchemaAwareDeserializer::new(
self.reader,
self.schema,
self.config,
)?)?;
remaining -= 1;
if remaining == 0 {
self.remaining = Self::read_block_header(self.reader)?;
} else {
self.remaining = Some(remaining);
}
Ok(Some((key, value)))
} else {
Ok(None)
}
}
fn size_hint(&self) -> Option<usize> {
self.remaining
.map(|x| usize::try_from(x).unwrap_or(usize::MAX))
}
}