Repository: tafia/quick-xml
Pull request #302 (2021-08-10 17:52:34)

Fix warnings
- Fix warnings from https://github.com/rust-lang/rust/issues/79813:
  ```console
  warning: trailing semicolon in macro used in expression position
    --> src\events\attributes.rs:362:20
      |
  362 |                 }));
      |                    ^
  ...
  443 |             None => attr!(start_key..end_key),
      |                     ------------------------- in this macro invocation
      |
      = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
      = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
      = note: macro invocations at the end of a block are treated as expressions
      = note: to ignore the value produced by the macro, add a semicolon after the invocation of `attr`
      = note: this warning originates in the macro `attr` (in Nightly builds, run with -Z macro-backtrace for more info)
  ```
  Because in the end it's stay non-obvilious that macro return some value, I've moved out the `return` keyword from the macro.
- Fix a bug introduced in the 8481c44c6b0134ec62226a80efc482f7ce7f8f6e -- some errors do not propagated to the caller
- Remove unused import
- Some bit of documentation in the deserializer
- Remove excess `cfg` check -- it was already checked couple lines above.


Patch:
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 2a566f6..2dfba93 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -15,7 +15,6 @@ jobs:
     - name: Build
       run: cargo build
     - name: Run tests (no features)
-      run: cargo test
       run: cargo test --no-default-features
     - name: Run tests (serialize)
       run: cargo test --features serialize
diff --git a/src/de/map.rs b/src/de/map.rs
index 90387ca..3682695 100644
--- a/src/de/map.rs
+++ b/src/de/map.rs
@@ -1,7 +1,9 @@
 //! Serde `Deserializer` module
 
 use crate::{
-    de::{escape::EscapedDeserializer, BorrowingReader, Deserializer, INNER_VALUE},
+    de::{
+        escape::EscapedDeserializer, BorrowingReader, Deserializer, INNER_VALUE, UNFLATTEN_PREFIX,
+    },
     errors::serialize::DeError,
     events::{BytesStart, Event},
 };
@@ -9,8 +11,16 @@ use serde::de::{self, DeserializeSeed, IntoDeserializer};
 
 enum MapValue {
     Empty,
-    Attribute { value: Vec<u8> },
+    /// Value should be deserialized from the attribute value
+    Attribute {
+        value: Vec<u8>,
+    },
     Nested,
+    /// Value should be deserialized from the text content of the XML node:
+    ///
+    /// ```xml
+    /// <...>text content for field value<...>
+    /// ```
     InnerValue,
 }
 
@@ -58,6 +68,7 @@ impl<'de, 'a, R: BorrowingReader<'de> + 'a> de::MapAccess<'de> for MapAccess<'de
     ) -> Result<Option<K::Value>, Self::Error> {
         let decoder = self.de.reader.decoder();
         let has_value_field = self.de.has_value_field;
+        let has_unflatten_field = self.de.has_unflatten_field;
         if let Some((key, value)) = self.next_attr()? {
             // try getting map from attributes (key= "value")
             self.value = MapValue::Attribute { value };
@@ -68,6 +79,9 @@ impl<'de, 'a, R: BorrowingReader<'de> + 'a> de::MapAccess<'de> for MapAccess<'de
             match self.de.peek()? {
                 Some(Event::Text(_)) => {
                     self.value = MapValue::InnerValue;
+                    // Deserialize `key` from special attribute name which means
+                    // that value should be taken from the text content of the
+                    // XML node
                     seed.deserialize(INNER_VALUE.into_deserializer()).map(Some)
                 }
                 // Used to deserialize collections of enums, like:
diff --git a/src/de/mod.rs b/src/de/mod.rs
index a9cfe38..e866c91 100644
--- a/src/de/mod.rs
+++ b/src/de/mod.rs
@@ -130,6 +130,13 @@ pub(crate) const UNFLATTEN_PREFIX: &str = "$unflatten=";
 pub struct Deserializer<'de, R: BorrowingReader<'de>> {
     reader: R,
     peek: Option<Event<'de>>,
+    /// Special sing that deserialized struct have a field with the special
+    /// name (see constant `INNER_VALUE`). That field should be deserialized
+    /// from the text content of the XML node:
+    ///
+    /// ```xml
+    /// <tag>value for INNER_VALUE field<tag>
+    /// ```
     has_value_field: bool,
     has_unflatten_field: bool,
 }
@@ -282,6 +289,7 @@ impl<'de, 'a, R: BorrowingReader<'de>> de::Deserializer<'de> for &'a mut Deseria
         fields: &'static [&'static str],
         visitor: V,
     ) -> Result<V::Value, DeError> {
+        // Try to go to the next `<tag ...>...</tag>` or `<tag .../>`
         if let Some(e) = self.next_start()? {
             let name = e.name().to_vec();
             self.has_value_field = fields.contains(&INNER_VALUE);
@@ -318,7 +326,6 @@ impl<'de, 'a, R: BorrowingReader<'de>> de::Deserializer<'de> for &'a mut Deseria
 
         #[cfg(feature = "encoding")]
         {
-            #[cfg(feature = "encoding")]
             let value = self.reader.decoder().decode(&*txt);
 
             match value.as_ref() {
diff --git a/src/events/attributes.rs b/src/events/attributes.rs
index cb4571e..cc4b1f4 100644
--- a/src/events/attributes.rs
+++ b/src/events/attributes.rs
@@ -349,14 +349,14 @@ impl<'a> Iterator for Attributes<'a> {
                 if self.html {
                     attr!($key, 0..0)
                 } else {
-                    return None;
-                };
+                    None
+                }
             }};
             ($key:expr, $val:expr) => {
-                return Some(Ok(Attribute {
+                Some(Ok(Attribute {
                     key: &self.bytes[$key],
                     value: Cow::Borrowed(&self.bytes[$val]),
-                }));
+                }))
             };
         }
 
@@ -373,7 +373,7 @@ impl<'a> Iterator for Attributes<'a> {
             .find(|&(_, &b)| !is_whitespace(b))
         {
             Some((i, _)) => i,
-            None => attr!(self.position..len),
+            None => return attr!(self.position..len),
         };
 
         // key ends with either whitespace or =
@@ -391,17 +391,17 @@ impl<'a> Iterator for Attributes<'a> {
                     Some((_, &b'=')) => i,
                     Some((j, _)) if self.html => {
                         self.position = j - 1;
-                        attr!(start_key..i, 0..0);
+                        return attr!(start_key..i, 0..0);
                     }
                     Some((j, _)) => err!(Error::NoEqAfterName(j)),
                     None if self.html => {
                         self.position = len;
-                        attr!(start_key..len, 0..0);
+                        return attr!(start_key..len, 0..0);
                     }
                     None => err!(Error::NoEqAfterName(len)),
                 }
             }
-            None => attr!(start_key..len),
+            None => return attr!(start_key..len),
         };
 
         if self.with_checks {
@@ -423,7 +423,7 @@ impl<'a> Iterator for Attributes<'a> {
                 match bytes.by_ref().find(|&(_, &b)| b == *quote) {
                     Some((j, _)) => {
                         self.position = j + 1;
-                        attr!(start_key..end_key, i + 1..j)
+                        return attr!(start_key..end_key, i + 1..j);
                     }
                     None => err!(Error::UnquotedValue(i)),
                 }
@@ -434,10 +434,10 @@ impl<'a> Iterator for Attributes<'a> {
                     .find(|&(_, &b)| is_whitespace(b))
                     .map_or(len, |(j, _)| j);
                 self.position = j;
-                attr!(start_key..end_key, i..j)
+                return attr!(start_key..end_key, i..j);
             }
             Some((i, _)) => err!(Error::UnquotedValue(i)),
-            None => attr!(start_key..end_key),
+            None => return attr!(start_key..end_key),
         }
     }
 }
diff --git a/src/se/var.rs b/src/se/var.rs
index 93797d4..1c4e488 100644
--- a/src/se/var.rs
+++ b/src/se/var.rs
@@ -1,11 +1,11 @@
 use crate::{
+    de::{INNER_VALUE, UNFLATTEN_PREFIX},
     errors::{serialize::DeError, Error},
     events::{BytesEnd, BytesStart, Event},
     se::Serializer,
     writer::Writer,
 };
-use de::{INNER_VALUE, UNFLATTEN_PREFIX};
-use serde::ser::{self, Serialize, SerializeMap};
+use serde::ser::{self, Serialize};
 use serde::Serializer as _;
 use std::io::Write;
 
@@ -127,7 +127,7 @@ where
         if key.starts_with(UNFLATTEN_PREFIX) {
             let key = key.split_at(UNFLATTEN_PREFIX.len()).1;
             let mut serializer = Serializer::with_root(writer, Some(key));
-            serializer.serialize_newtype_struct(key, value);
+            serializer.serialize_newtype_struct(key, value)?;
             self.children.append(&mut self.buffer);
         } else {
             let mut serializer = Serializer::with_root(writer, Some(key));


Test patch:
diff --git a/tests/xmlrs_reader_tests.rs b/tests/xmlrs_reader_tests.rs
index 3a0c705..d396fc0 100644
--- a/tests/xmlrs_reader_tests.rs
+++ b/tests/xmlrs_reader_tests.rs
@@ -53,8 +53,8 @@ fn sample_2_full() {
 #[ignore]
 fn html5() {
     test(
-        include_bytes!("documents/html5.html"),
-        include_bytes!("documents/html5.txt"),
+        include_str!("documents/html5.html"),
+        include_str!("documents/html5.txt"),
         false,
     );
 }
@@ -65,8 +65,8 @@ fn html5() {
 #[ignore]
 fn html5() {
     test(
-        include_bytes!("documents/html5.html"),
-        include_bytes!("documents/html5-windows.txt"),
+        include_str!("documents/html5.html"),
+        include_str!("documents/html5-windows.txt"),
         false,
     );
 }