Skip to content

Commit

Permalink
Fix #580: deserialize newtypes using Visitor::visit_newtype_struct in…
Browse files Browse the repository at this point in the history
…stead of visit_seq

The problem was in `SeqItemDeserializer::deserialize_newtype_struct`. Previously it was
the same as `SeqItemDeserializer::deserialize_seq`, but deserializing sequences in this
deserializer assumes, that those sequences are `xs:list`s, because deserializer itself
represents a list element.

In the original bug report an `UnexpectedEof` is returning. The error was changed in the
pre-previous commit (3d5ed69) and in this it is fixed.

The following tests checks that all's OK:

- Deserializer::deserialize_newtype_struct is reached by:
  - serde-de:
    - newtype::excess_attribute
    - newtype::simple
  - serde-se:
    - with_root::newtype
    - without_root::newtype

- MapValueDeserializer::deserialize_newtype_struct is reached by:
  - serde-issues:
    - issue343

- SeqItemDeserializer::deserialize_newtype_struct is reached by:
  - serde-issues:
    - issue580
  • Loading branch information
Mingun committed Oct 4, 2023
1 parent 22f60d1 commit 1077d00
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 12 deletions.
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ MSRV bumped to 1.56! Crate now uses Rust 2021 edition.

- [#660]: Fixed incorrect deserialization of `xs:list`s from empty tags (`<tag/>`
or `<tag></tag>`). Previously an `DeError::UnexpectedEof")` was returned in that case
- [#580]: Fixed incorrect deserialization of vectors of newtypes from sequences of tags.

### Misc Changes

Expand All @@ -35,6 +36,7 @@ MSRV bumped to 1.56! Crate now uses Rust 2021 edition.
(and newly added `ElementWriter::write_inner_content_async` of course).

[#545]: https://github.com/tafia/quick-xml/pull/545
[#580]: https://github.com/tafia/quick-xml/issues/580
[#619]: https://github.com/tafia/quick-xml/issues/619
[#635]: https://github.com/tafia/quick-xml/pull/635
[#643]: https://github.com/tafia/quick-xml/pull/643
Expand Down
27 changes: 27 additions & 0 deletions src/de/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,19 @@ where
deserialize_option!(self.map.de, self, visitor)
}

/// Forwards deserialization of the inner type. Always calls [`Visitor::visit_newtype_struct`]
/// with the same deserializer.
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)
}

/// Deserializes each `<tag>` in
/// ```xml
/// <any-tag>
Expand Down Expand Up @@ -869,6 +882,20 @@ where
deserialize_option!(self.map.de, self, visitor)
}

/// Forwards deserialization of the inner type. Always calls [`Visitor::visit_newtype_struct`]
/// with the [`SimpleTypeDeserializer`].
fn deserialize_newtype_struct<V>(
mut self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let text = self.read_string()?;
visitor.visit_newtype_struct(SimpleTypeDeserializer::from_text(text))
}

/// This method deserializes a sequence inside of element that itself is a
/// sequence element:
///
Expand Down
25 changes: 13 additions & 12 deletions src/de/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1904,18 +1904,6 @@ macro_rules! deserialize_primitives {
self.deserialize_unit(visitor)
}

/// Representation of the newtypes the same as one-element [tuple](#method.deserialize_tuple).
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, DeError>
where
V: Visitor<'de>,
{
self.deserialize_tuple(1, visitor)
}

/// Representation of tuples the same as [sequences](#method.deserialize_seq).
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, DeError>
where
Expand Down Expand Up @@ -2839,6 +2827,19 @@ where
}
}

/// Forwards deserialization of the inner type. Always calls [`Visitor::visit_newtype_struct`]
/// with the same deserializer.
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, DeError>
where
V: Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}

fn deserialize_enum<V>(
self,
_name: &'static str,
Expand Down

0 comments on commit 1077d00

Please sign in to comment.