use crate::error::Error;
use forma_core::de::*;
use sif::{Document, Record, Schema, Value as SifValue};
pub struct Deserializer<'de> {
doc: &'de Document,
section: usize,
}
impl<'de> Deserializer<'de> {
pub fn new(doc: &'de Document) -> Self {
Deserializer { doc, section: 0 }
}
fn schema(&self) -> Result<&'de Schema, Error> {
self.doc
.sections
.get(self.section)
.and_then(|s| s.schema.as_ref())
.ok_or(Error::NoSchema)
}
fn records(&self) -> &'de [Record] {
self.doc
.sections
.get(self.section)
.map(|s| s.records.as_slice())
.unwrap_or(&[])
}
}
impl<'de, 'a> forma_core::de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
self.deserialize_seq(visitor)
}
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
let schema = self.schema()?;
let records = self.records();
visitor.visit_seq(RecordSeqAccess {
schema,
records,
index: 0,
})
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error> {
let schema = self.schema()?;
let records = self.records();
if records.is_empty() {
return Err(Error::Eof);
}
visitor.visit_map(RecordMapAccess::new(schema, &records[0]))
}
forma_core::forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct
tuple tuple_struct map enum identifier ignored_any
}
}
struct RecordSeqAccess<'de> {
schema: &'de Schema,
records: &'de [Record],
index: usize,
}
impl<'de> SeqAccess<'de> for RecordSeqAccess<'de> {
type Error = Error;
fn next_element_seed<T: DeserializeSeed<'de>>(
&mut self,
seed: T,
) -> Result<Option<T::Value>, Error> {
if self.index >= self.records.len() {
return Ok(None);
}
let record = &self.records[self.index];
self.index += 1;
let de = RecordDeserializer {
schema: self.schema,
record,
};
seed.deserialize(de).map(Some)
}
fn size_hint(&self) -> Option<usize> {
Some(self.records.len() - self.index)
}
}
struct RecordDeserializer<'de> {
schema: &'de Schema,
record: &'de Record,
}
impl<'de> forma_core::de::Deserializer<'de> for RecordDeserializer<'de> {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
visitor.visit_map(RecordMapAccess::new(self.schema, self.record))
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error> {
visitor.visit_map(RecordMapAccess::new(self.schema, self.record))
}
forma_core::forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq
tuple tuple_struct map enum identifier ignored_any
}
}
struct RecordMapAccess<'de> {
schema: &'de Schema,
record: &'de Record,
field_index: usize,
}
impl<'de> RecordMapAccess<'de> {
fn new(schema: &'de Schema, record: &'de Record) -> Self {
RecordMapAccess {
schema,
record,
field_index: 0,
}
}
}
impl<'de> MapAccess<'de> for RecordMapAccess<'de> {
type Error = Error;
fn next_key_seed<K: DeserializeSeed<'de>>(
&mut self,
seed: K,
) -> Result<Option<K::Value>, Error> {
if self.field_index >= self.schema.fields.len() {
return Ok(None);
}
let name = &self.schema.fields[self.field_index].name;
seed.deserialize(StrDeserializer(name.as_str())).map(Some)
}
fn next_value_seed<V: DeserializeSeed<'de>>(
&mut self,
seed: V,
) -> Result<V::Value, Error> {
let idx = self.field_index;
self.field_index += 1;
let value = self
.record
.values
.get(idx)
.unwrap_or(&SifValue::Null);
seed.deserialize(ValueDeserializer {
value,
field_name: &self.schema.fields[idx].name,
})
}
fn size_hint(&self) -> Option<usize> {
Some(self.schema.fields.len() - self.field_index)
}
}
struct StrDeserializer<'de>(&'de str);
impl<'de> forma_core::de::Deserializer<'de> for StrDeserializer<'de> {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
visitor.visit_borrowed_str(self.0)
}
forma_core::forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq
tuple tuple_struct map struct_type enum identifier ignored_any
}
}
struct ValueDeserializer<'de> {
value: &'de SifValue,
field_name: &'de str,
}
impl<'de> forma_core::de::Deserializer<'de> for ValueDeserializer<'de> {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Null => visitor.visit_none(),
SifValue::Bool(b) => visitor.visit_bool(*b),
SifValue::Int(n) => visitor.visit_i64(*n),
SifValue::Uint(n) => visitor.visit_u64(*n),
SifValue::Float(n) => visitor.visit_f64(*n),
SifValue::Str(s) => visitor.visit_str(s.as_str()),
SifValue::Date(s) | SifValue::DateTime(s) | SifValue::Duration(s) | SifValue::Enum(s) => {
visitor.visit_str(s.as_str())
}
SifValue::Bytes(b) => visitor.visit_bytes(b),
SifValue::Array(arr) => {
visitor.visit_seq(SifArrayAccess { arr, index: 0, field_name: self.field_name })
}
SifValue::Map(entries) => {
visitor.visit_map(SifMapAccess {
entries,
index: 0,
field_name: self.field_name,
})
}
}
}
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Null => visitor.visit_none(),
_ => visitor.visit_some(self),
}
}
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Str(s) | SifValue::Date(s) | SifValue::DateTime(s)
| SifValue::Duration(s) | SifValue::Enum(s) => visitor.visit_str(s.as_str()),
other => visitor.visit_str(&value_to_string(other)),
}
}
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
self.deserialize_str(visitor)
}
fn deserialize_enum<V: Visitor<'de>>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error> {
match self.value {
SifValue::Str(s) | SifValue::Enum(s) => visitor.visit_enum(SifEnumAccess(s.as_str())),
SifValue::Bool(b) => visitor.visit_enum(SifEnumAccessOwned(if *b { "T".into() } else { "F".into() })),
SifValue::Int(n) => visitor.visit_enum(SifEnumAccessOwned(n.to_string())),
SifValue::Uint(n) => visitor.visit_enum(SifEnumAccessOwned(n.to_string())),
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "enum variant string".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Bool(b) => visitor.visit_bool(*b),
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "bool".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> { self.deserialize_i64(visitor) }
fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> { self.deserialize_i64(visitor) }
fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> { self.deserialize_i64(visitor) }
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Int(n) => visitor.visit_i64(*n),
SifValue::Uint(n) => visitor.visit_i64(*n as i64),
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "int".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> { self.deserialize_u64(visitor) }
fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> { self.deserialize_u64(visitor) }
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> { self.deserialize_u64(visitor) }
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Uint(n) => visitor.visit_u64(*n),
SifValue::Int(n) if *n >= 0 => visitor.visit_u64(*n as u64),
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "uint".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> { self.deserialize_f64(visitor) }
fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Float(n) => visitor.visit_f64(*n),
SifValue::Int(n) => visitor.visit_f64(*n as f64),
SifValue::Uint(n) => visitor.visit_u64(*n),
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "float".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Str(s) => {
let mut chars = s.chars();
match (chars.next(), chars.next()) {
(Some(c), None) => visitor.visit_char(c),
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "single character".into(),
got: "multi-char string".into(),
}),
}
}
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "char".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Bytes(b) => visitor.visit_bytes(b),
_ => self.deserialize_seq(visitor),
}
}
fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Bytes(b) => visitor.visit_byte_buf(b.clone()),
_ => self.deserialize_seq(visitor),
}
}
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Null => visitor.visit_unit(),
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "null".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_unit_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Error> {
self.deserialize_unit(visitor)
}
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Error> {
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Array(arr) => {
visitor.visit_seq(SifArrayAccess { arr, index: 0, field_name: self.field_name })
}
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "array".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_tuple<V: Visitor<'de>>(self, _len: usize, visitor: V) -> Result<V::Value, Error> {
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value, Error> {
self.deserialize_seq(visitor)
}
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
match self.value {
SifValue::Map(entries) => {
visitor.visit_map(SifMapAccess {
entries,
index: 0,
field_name: self.field_name,
})
}
_ => Err(Error::TypeMismatch {
field: self.field_name.to_string(),
expected: "map".into(),
got: value_type_name(self.value).into(),
}),
}
}
fn deserialize_struct<V: Visitor<'de>>(
self,
_name: &'static str,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error> {
self.deserialize_map(visitor)
}
fn deserialize_identifier<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
self.deserialize_str(visitor)
}
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
self.deserialize_any(visitor)
}
}
struct SifArrayAccess<'de> {
arr: &'de [SifValue],
index: usize,
field_name: &'de str,
}
impl<'de> SeqAccess<'de> for SifArrayAccess<'de> {
type Error = Error;
fn next_element_seed<T: DeserializeSeed<'de>>(
&mut self,
seed: T,
) -> Result<Option<T::Value>, Error> {
if self.index >= self.arr.len() {
return Ok(None);
}
let value = &self.arr[self.index];
self.index += 1;
seed.deserialize(ValueDeserializer {
value,
field_name: self.field_name,
})
.map(Some)
}
fn size_hint(&self) -> Option<usize> {
Some(self.arr.len() - self.index)
}
}
struct SifMapAccess<'de> {
entries: &'de [(String, SifValue)],
index: usize,
field_name: &'de str,
}
impl<'de> MapAccess<'de> for SifMapAccess<'de> {
type Error = Error;
fn next_key_seed<K: DeserializeSeed<'de>>(
&mut self,
seed: K,
) -> Result<Option<K::Value>, Error> {
if self.index >= self.entries.len() {
return Ok(None);
}
let (key, _) = &self.entries[self.index];
seed.deserialize(StrDeserializer(key.as_str())).map(Some)
}
fn next_value_seed<V: DeserializeSeed<'de>>(
&mut self,
seed: V,
) -> Result<V::Value, Error> {
let (_, value) = &self.entries[self.index];
self.index += 1;
seed.deserialize(ValueDeserializer {
value,
field_name: self.field_name,
})
}
}
struct SifEnumAccess<'de>(&'de str);
impl<'de> EnumAccess<'de> for SifEnumAccess<'de> {
type Error = Error;
type Variant = UnitOnly;
fn variant_seed<V: DeserializeSeed<'de>>(
self,
seed: V,
) -> Result<(V::Value, UnitOnly), Error> {
let variant = seed.deserialize(StrDeserializer(self.0))?;
Ok((variant, UnitOnly))
}
}
struct SifEnumAccessOwned(String);
impl<'de> EnumAccess<'de> for SifEnumAccessOwned {
type Error = Error;
type Variant = UnitOnly;
fn variant_seed<V: DeserializeSeed<'de>>(
self,
seed: V,
) -> Result<(V::Value, UnitOnly), Error> {
let variant = seed.deserialize(OwnedStrDeserializer(self.0))?;
Ok((variant, UnitOnly))
}
}
struct OwnedStrDeserializer(String);
impl<'de> forma_core::de::Deserializer<'de> for OwnedStrDeserializer {
type Error = Error;
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value, Error> {
visitor.visit_string(self.0)
}
forma_core::forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq
tuple tuple_struct map struct_type enum identifier ignored_any
}
}
struct UnitOnly;
impl<'de> VariantAccess<'de> for UnitOnly {
type Error = Error;
fn unit_variant(self) -> Result<(), Error> {
Ok(())
}
fn newtype_variant_seed<T: DeserializeSeed<'de>>(self, _seed: T) -> Result<T::Value, Error> {
Err(Error::Message("expected unit variant, got newtype".into()))
}
fn tuple_variant<V: Visitor<'de>>(self, _len: usize, _visitor: V) -> Result<V::Value, Error> {
Err(Error::Message("expected unit variant, got tuple".into()))
}
fn struct_variant<V: Visitor<'de>>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Error> {
Err(Error::Message("expected unit variant, got struct".into()))
}
}
fn value_type_name(v: &SifValue) -> &'static str {
match v {
SifValue::Null => "null",
SifValue::Bool(_) => "bool",
SifValue::Int(_) => "int",
SifValue::Uint(_) => "uint",
SifValue::Float(_) => "float",
SifValue::Str(_) => "str",
SifValue::Date(_) => "date",
SifValue::DateTime(_) => "datetime",
SifValue::Duration(_) => "duration",
SifValue::Bytes(_) => "bytes",
SifValue::Enum(_) => "enum",
SifValue::Array(_) => "array",
SifValue::Map(_) => "map",
}
}
fn value_to_string(v: &SifValue) -> String {
match v {
SifValue::Null => "_".to_string(),
SifValue::Bool(b) => b.to_string(),
SifValue::Int(n) => n.to_string(),
SifValue::Uint(n) => n.to_string(),
SifValue::Float(n) => n.to_string(),
SifValue::Str(s) | SifValue::Date(s) | SifValue::DateTime(s)
| SifValue::Duration(s) | SifValue::Enum(s) => s.clone(),
SifValue::Bytes(_) => "<bytes>".to_string(),
SifValue::Array(_) => "<array>".to_string(),
SifValue::Map(_) => "<map>".to_string(),
}
}