Skip to content

Commit

Permalink
Use QNameDeserializer instead of VariantDeseriaizer
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingun committed Jan 7, 2023
1 parent e0b372f commit ac3c3d5
Showing 1 changed file with 3 additions and 228 deletions.
231 changes: 3 additions & 228 deletions src/de/var.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use crate::{
de::key::QNameDeserializer,
de::simple_type::SimpleTypeDeserializer,
de::{deserialize_bool, DeEvent, Deserializer, XmlRead, TEXT_KEY},
encoding::Decoder,
de::{DeEvent, Deserializer, XmlRead, TEXT_KEY},
errors::serialize::DeError,
escape::unescape,
};
use serde::de::value::StrDeserializer;
use serde::de::{self, DeserializeSeed, Deserializer as _, Visitor};
use serde::{forward_to_deserialize_any, serde_if_integer128};
use std::borrow::Cow;

/// An enum access
pub struct EnumAccess<'de, 'a, R>
Expand Down Expand Up @@ -41,11 +38,7 @@ where
let decoder = self.de.reader.decoder();
let (name, is_text) = match self.de.peek()? {
DeEvent::Start(e) => (
seed.deserialize(VariantDeserializer::new(
e.local_name().into_inner(),
decoder,
false,
))?,
seed.deserialize(QNameDeserializer::from_elem(e.name(), decoder)?)?,
false,
),
DeEvent::Text(_) | DeEvent::CData(_) => (
Expand Down Expand Up @@ -153,221 +146,3 @@ where
}
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

/// A deserializer for a xml escaped and encoded value
///
/// # Note
///
/// Escaping the value is actually not always necessary, for instance
/// when converting to float, we don't expect any escapable character
/// anyway
#[derive(Clone, Debug)]
struct VariantDeserializer<'a> {
/// Possible escaped value of text/CDATA or tag name value
escaped_value: &'a [u8],
/// If `true`, value requires unescaping before using
escaped: bool,
decoder: Decoder,
}

impl<'a> VariantDeserializer<'a> {
pub fn new(escaped_value: &'a [u8], decoder: Decoder, escaped: bool) -> Self {
Self {
decoder,
escaped_value,
escaped,
}
}
}

macro_rules! deserialize_num {
($method:ident, $visit:ident) => {
fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let value = self.decoder.decode(self.escaped_value)?.parse()?;

visitor.$visit(value)
}
};
}

impl<'de, 'a> de::Deserializer<'de> for VariantDeserializer<'a> {
type Error = DeError;

deserialize_num!(deserialize_i8, visit_i8);
deserialize_num!(deserialize_i16, visit_i16);
deserialize_num!(deserialize_i32, visit_i32);
deserialize_num!(deserialize_i64, visit_i64);

deserialize_num!(deserialize_u8, visit_u8);
deserialize_num!(deserialize_u16, visit_u16);
deserialize_num!(deserialize_u32, visit_u32);
deserialize_num!(deserialize_u64, visit_u64);

deserialize_num!(deserialize_f32, visit_f32);
deserialize_num!(deserialize_f64, visit_f64);

serde_if_integer128! {
deserialize_num!(deserialize_i128, visit_i128);
deserialize_num!(deserialize_u128, visit_u128);
}

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_str(visitor)
}

fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let decoded = self.decoder.decode(self.escaped_value)?;
if self.escaped {
match unescape(&decoded)? {
Cow::Borrowed(s) => visitor.visit_str(s),
Cow::Owned(s) => visitor.visit_string(s),
}
} else {
match decoded {
Cow::Borrowed(s) => visitor.visit_str(s),
Cow::Owned(s) => visitor.visit_string(s),
}
}
}

/// Returns [`DeError::Unsupported`]
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
Err(DeError::Unsupported(
"binary data content is not supported by XML format".into(),
))
}

/// Forwards deserialization to the [`deserialize_bytes`](#method.deserialize_bytes)
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_bytes(visitor)
}

fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_str(visitor)
}

fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
deserialize_bool(self.escaped_value, self.decoder, visitor)
}

fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_str(visitor)
}

fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}

fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if self.escaped_value.is_empty() {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}

fn deserialize_enum<V>(
self,
_name: &str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_enum(self)
}

fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}

forward_to_deserialize_any! {
unit_struct seq tuple tuple_struct map struct identifier ignored_any
}
}

impl<'de, 'a> de::EnumAccess<'de> for VariantDeserializer<'a> {
type Error = DeError;
type Variant = Self;

fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Self::Error>
where
V: DeserializeSeed<'de>,
{
let name = seed.deserialize(self.clone())?;
Ok((name, self))
}
}

impl<'de, 'a> de::VariantAccess<'de> for VariantDeserializer<'a> {
type Error = DeError;

fn unit_variant(self) -> Result<(), Self::Error> {
Ok(())
}

fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
seed.deserialize(self)
}

fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!()
}

fn struct_variant<V>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
unimplemented!()
}
}

0 comments on commit ac3c3d5

Please sign in to comment.