use crate::reader::event::Event;
use crate::reader::value_descriptor::{Object, Primitive, ValueDescriptor};
use crate::reader::{Chunk, Error};
use serde::de::value::StrDeserializer;
use serde::de::{DeserializeSeed, IntoDeserializer, Visitor};
use serde::forward_to_deserialize_any;
use std::fmt::Display;
struct Deserializer<'de> {
chunk: &'de Chunk,
value: &'de ValueDescriptor,
}
impl<'de> Deserializer<'de> {
pub fn new(chunk: &'de Chunk, value: &'de ValueDescriptor) -> Self {
Self { chunk, value }
}
}
impl serde::de::Error for Error {
fn custom<T>(msg: T) -> Self
where
T: Display,
{
Error::DeserializeError(msg.to_string())
}
}
pub fn from_event<'a, T>(event: &'a Event) -> crate::reader::Result<T>
where
T: serde::de::Deserialize<'a>,
{
T::deserialize(Deserializer::new(event.chunk, &event.value))
}
pub fn from_value_descriptor<'a, T>(
chunk: &'a Chunk,
value: &'a ValueDescriptor,
) -> crate::reader::Result<T>
where
T: serde::de::Deserialize<'a>,
{
T::deserialize(Deserializer::new(chunk, value))
}
struct ObjectDeserializer<'de> {
chunk: &'de Chunk,
field_idx: usize,
value: &'de Object,
}
impl<'de> serde::de::MapAccess<'de> for ObjectDeserializer<'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
where
K: DeserializeSeed<'de>,
{
if self.field_idx >= self.value.fields.len() {
return Ok(None);
}
if let Some(key) = self
.chunk
.metadata
.type_pool
.get(self.value.class_id)
.map(|t| t.fields[self.field_idx].name())
{
let key: StrDeserializer<Self::Error> = key.into_deserializer();
let key: K::Value = seed.deserialize(key)?;
Ok(Some(key))
} else {
Err(Error::ClassNotFound(self.value.class_id))
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
where
V: DeserializeSeed<'de>,
{
assert!(self.field_idx < self.value.fields.len());
let value = seed.deserialize(Deserializer::new(
self.chunk,
&self.value.fields[self.field_idx],
))?;
self.field_idx += 1;
Ok(value)
}
}
struct ArrayDeserializer<'de> {
chunk: &'de Chunk,
array_idx: usize,
value: &'de Vec<ValueDescriptor>,
}
impl<'de> serde::de::SeqAccess<'de> for ArrayDeserializer<'de> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: DeserializeSeed<'de>,
{
if self.array_idx >= self.value.len() {
return Ok(None);
}
let value = seed.deserialize(Deserializer::new(self.chunk, &self.value[self.array_idx]))?;
self.array_idx += 1;
Ok(Some(value))
}
}
impl<'de> serde::Deserializer<'de> for Deserializer<'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
use crate::reader::value_descriptor::Primitive::*;
use ValueDescriptor::Primitive;
match self.value {
Primitive(Integer(v)) => visitor.visit_i32(*v),
Primitive(Long(v)) => visitor.visit_i64(*v),
Primitive(Float(v)) => visitor.visit_f32(*v),
Primitive(Double(v)) => visitor.visit_f64(*v),
Primitive(Character(v)) => {
#[cfg(feature = "cstring")]
return visitor
.visit_borrowed_str(v.string.as_c_str().to_str().expect("Invalid UTF-8"));
#[cfg(not(feature = "cstring"))]
return visitor.visit_char(*v);
}
Primitive(Boolean(v)) => visitor.visit_bool(*v),
Primitive(Short(v)) => visitor.visit_i16(*v),
Primitive(Byte(v)) => visitor.visit_i8(*v),
Primitive(String(v)) => {
#[cfg(feature = "cstring")]
return visitor
.visit_borrowed_str(v.string.as_c_str().to_str().expect("Invalid UTF-8"));
#[cfg(not(feature = "cstring"))]
return visitor.visit_borrowed_str(v.as_str());
}
Primitive(NullString) => Err(Error::DeserializeError(
"Unexpected null string".to_string(),
)),
ValueDescriptor::Object(obj) => visitor.visit_map(ObjectDeserializer {
chunk: self.chunk,
field_idx: 0,
value: obj,
}),
ValueDescriptor::Array(array) => visitor.visit_seq(ArrayDeserializer {
chunk: self.chunk,
array_idx: 0,
value: array,
}),
ValueDescriptor::ConstantPool {
class_id,
constant_index,
} => match self.chunk.constant_pool.get(class_id, constant_index) {
Some(value) => Self::deserialize_any(Deserializer::new(self.chunk, value), visitor),
None => Err(Error::DeserializeError(format!(
"Not found in constant pool: class_id={}, index={}",
class_id, constant_index
))),
},
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self.value {
ValueDescriptor::Primitive(Primitive::NullString) => visitor.visit_none(),
ValueDescriptor::ConstantPool {
class_id,
constant_index,
} => match self.chunk.constant_pool.get(class_id, constant_index) {
Some(value) => visitor.visit_some(Deserializer::new(self.chunk, value)),
None => visitor.visit_none(),
},
_ => visitor.visit_some(self),
}
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf unit unit_struct newtype_struct seq tuple
tuple_struct map enum identifier ignored_any struct
}
}