Skip to content

Commit

Permalink
Merge pull request #312 from Mingun/refactoring
Browse files Browse the repository at this point in the history
Minor improvement in code quality, optimisations and `deserialize_unit` fix
  • Loading branch information
tafia authored Oct 19, 2021
2 parents 118c07b + 646484a commit 5724ece
Show file tree
Hide file tree
Showing 9 changed files with 526 additions and 355 deletions.
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
- refactor: unify errors when EOF encountered during serde deserialization
- test: ensure that after deserializing all XML was consumed
- feat: add `Deserializer::from_str` and `Deserializer::from_bytes`
- refactor: reduce number of unnecessary copies when deserialize numbers/booleans/identifiers
from the attribute and element names and attribute values
- fix: allow to deserialize `unit`s from text and CDATA content.
`DeError::InvalidUnit` variant is removed, because after fix it is no longer used

## 0.23.0-alpha3

Expand Down
64 changes: 64 additions & 0 deletions src/de/byte_buf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//! Helper types for tests

use serde::de::{self, Deserialize, Deserializer, Error};
use std::fmt;

/// Wrapper around `Vec<u8>` that deserialized using `deserialize_byte_buf`
/// instead of vector's generic `deserialize_seq`
#[derive(Debug, PartialEq)]
pub struct ByteBuf(pub Vec<u8>);

impl<'de> Deserialize<'de> for ByteBuf {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct Visitor;

impl<'de> de::Visitor<'de> for Visitor {
type Value = ByteBuf;

fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("byte data")
}

fn visit_bytes<E: Error>(self, v: &[u8]) -> Result<Self::Value, E> {
Ok(ByteBuf(v.to_vec()))
}

fn visit_byte_buf<E: Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
Ok(ByteBuf(v))
}
}

Ok(d.deserialize_byte_buf(Visitor)?)
}
}

/// Wrapper around `&[u8]` that deserialized using `deserialize_bytes`
/// instead of vector's generic `deserialize_seq`
#[derive(Debug, PartialEq)]
pub struct Bytes<'de>(pub &'de [u8]);

impl<'de> Deserialize<'de> for Bytes<'de> {
fn deserialize<D>(d: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct Visitor;

impl<'de> de::Visitor<'de> for Visitor {
type Value = Bytes<'de>;

fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("borrowed bytes")
}

fn visit_borrowed_bytes<E: Error>(self, v: &'de [u8]) -> Result<Self::Value, E> {
Ok(Bytes(v))
}
}

Ok(d.deserialize_bytes(Visitor)?)
}
}
93 changes: 36 additions & 57 deletions src/de/escape.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Serde `Deserializer` module

use crate::de::deserialize_bool;
use crate::{errors::serialize::DeError, errors::Error, escape::unescape, reader::Decoder};
use serde::de::{self, Visitor};
use serde::de::{DeserializeSeed, EnumAccess, VariantAccess, Visitor};
use serde::{self, forward_to_deserialize_any};
use std::borrow::Cow;

Expand All @@ -13,16 +14,16 @@ use std::borrow::Cow;
/// when converting to float, we don't expect any escapable character
/// anyway
#[derive(Clone, Debug)]
pub(crate) struct EscapedDeserializer {
pub struct EscapedDeserializer<'a> {
decoder: Decoder,
/// Possible escaped value of text/CDATA or attribute value
escaped_value: Vec<u8>,
escaped_value: Cow<'a, [u8]>,
/// If `true`, value requires unescaping before using
escaped: bool,
}

impl EscapedDeserializer {
pub fn new(escaped_value: Vec<u8>, decoder: Decoder, escaped: bool) -> Self {
impl<'a> EscapedDeserializer<'a> {
pub fn new(escaped_value: Cow<'a, [u8]>, decoder: Decoder, escaped: bool) -> Self {
EscapedDeserializer {
decoder,
escaped_value,
Expand All @@ -45,17 +46,17 @@ macro_rules! deserialize_num {
V: Visitor<'de>,
{
#[cfg(not(feature = "encoding"))]
let value = self.decoder.decode(&self.escaped_value)?.parse()?;
let value = self.decoder.decode(self.escaped_value.as_ref())?.parse()?;

#[cfg(feature = "encoding")]
let value = self.decoder.decode(&self.escaped_value).parse()?;
let value = self.decoder.decode(self.escaped_value.as_ref()).parse()?;

visitor.$visit(value)
}
};
}

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

fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
Expand Down Expand Up @@ -104,34 +105,7 @@ impl<'de> serde::Deserializer<'de> for EscapedDeserializer {
where
V: Visitor<'de>,
{
#[cfg(feature = "encoding")]
{
#[cfg(feature = "encoding")]
let value = self.decoder.decode(&self.escaped_value);

match value.as_ref() {
"true" | "1" | "True" | "TRUE" | "t" | "Yes" | "YES" | "yes" | "y" => {
visitor.visit_bool(true)
}
"false" | "0" | "False" | "FALSE" | "f" | "No" | "NO" | "no" | "n" => {
visitor.visit_bool(false)
}
_ => Err(DeError::InvalidBoolean(value.into())),
}
}

#[cfg(not(feature = "encoding"))]
{
match &*self.escaped_value {
b"true" | b"1" | b"True" | b"TRUE" | b"t" | b"Yes" | b"YES" | b"yes" | b"y" => {
visitor.visit_bool(true)
}
b"false" | b"0" | b"False" | b"FALSE" | b"f" | b"No" | b"NO" | b"no" | b"n" => {
visitor.visit_bool(false)
}
e => Err(DeError::InvalidBoolean(self.decoder.decode(e)?.into())),
}
}
deserialize_bool(self.escaped_value.as_ref(), self.decoder, visitor)
}

fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
Expand All @@ -152,19 +126,22 @@ impl<'de> serde::Deserializer<'de> for EscapedDeserializer {
where
V: Visitor<'de>,
{
if self.escaped_value.is_empty() {
if self.escaped_value.as_ref().is_empty() {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}

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

Expand Down Expand Up @@ -195,46 +172,48 @@ impl<'de> serde::Deserializer<'de> for EscapedDeserializer {
}
}

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

fn variant_seed<V: de::DeserializeSeed<'de>>(
self,
seed: V,
) -> Result<(V::Value, Self), DeError> {
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> de::VariantAccess<'de> for EscapedDeserializer {
impl<'de, 'a> VariantAccess<'de> for EscapedDeserializer<'a> {
type Error = DeError;

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

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

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

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

0 comments on commit 5724ece

Please sign in to comment.