diff --git a/benches/macrobenches.rs b/benches/macrobenches.rs index 9a87f31d..77197b3e 100644 --- a/benches/macrobenches.rs +++ b/benches/macrobenches.rs @@ -1,3 +1,7 @@ +// std::hint::black_box stable since 1.66, but our MSRV = 1.56. +// criterion::black_box is deprecated in since criterion 0.7. +// Running benchmarks assumed on current Rust version, so this should be fine +#![allow(clippy::incompatible_msrv)] use criterion::{self, criterion_group, criterion_main, Criterion, Throughput}; use quick_xml::events::Event; use quick_xml::reader::{NsReader, Reader}; diff --git a/benches/microbenches.rs b/benches/microbenches.rs index f0ae8816..f6af550f 100644 --- a/benches/microbenches.rs +++ b/benches/microbenches.rs @@ -1,3 +1,7 @@ +// std::hint::black_box stable since 1.66, but our MSRV = 1.56. +// criterion::black_box is deprecated in since criterion 0.7. +// Running benchmarks assumed on current Rust version, so this should be fine +#![allow(clippy::incompatible_msrv)] use criterion::{self, criterion_group, criterion_main, Criterion}; use pretty_assertions::assert_eq; use quick_xml::escape::{escape, unescape}; diff --git a/examples/flattened_enum.rs b/examples/flattened_enum.rs index 1019c1de..c56c2fca 100644 --- a/examples/flattened_enum.rs +++ b/examples/flattened_enum.rs @@ -129,7 +129,7 @@ fn main() { "#; - let model: Model = from_str(&x).unwrap(); + let model: Model = from_str(x).unwrap(); println!("{:?}", model); // Model { elem: [Foo(Foo { a: "1", subfoo: SubFoo { a1: "2", a2: "42", a3: "1337" } }), Bar(Bar { b: "22" })] } diff --git a/src/de/key.rs b/src/de/key.rs index aa190297..bf5ba5fc 100644 --- a/src/de/key.rs +++ b/src/de/key.rs @@ -96,7 +96,7 @@ impl<'i, 'd> QNameDeserializer<'i, 'd> { // can apper only in this literal form, as `xml` prefix cannot be redeclared or unbound let (local, prefix_opt) = name.decompose(); if prefix_opt.map_or(false, |prefix| prefix.is_xml()) { - decoder.decode_into(&name.into_inner(), key_buf)?; + decoder.decode_into(name.into_inner(), key_buf)?; } else { decoder.decode_into(local.into_inner(), key_buf)?; } diff --git a/src/de/map.rs b/src/de/map.rs index 2c1e8953..b3ddfa20 100644 --- a/src/de/map.rs +++ b/src/de/map.rs @@ -207,8 +207,8 @@ where de: &'d mut Deserializer<'de, R, E>, start: BytesStart<'de>, fields: &'static [&'static str], - ) -> Result { - Ok(Self { + ) -> Self { + Self { de, iter: IterState::new(start.name().as_ref().len(), false), start, @@ -216,7 +216,7 @@ where fields, has_value_field: fields.contains(&VALUE_KEY), has_text_field: fields.contains(&TEXT_KEY), - }) + } } /// Determines if subtree started with the specified event shoould be skipped. @@ -801,7 +801,7 @@ where V: Visitor<'de>, { match self.map.de.next()? { - DeEvent::Start(e) => visitor.visit_map(ElementMapAccess::new(self.map.de, e, fields)?), + DeEvent::Start(e) => visitor.visit_map(ElementMapAccess::new(self.map.de, e, fields)), DeEvent::Text(e) => { SimpleTypeDeserializer::from_text_content(e).deserialize_struct("", fields, visitor) } @@ -1144,7 +1144,7 @@ where where V: Visitor<'de>, { - visitor.visit_map(ElementMapAccess::new(self.de, self.start, fields)?) + visitor.visit_map(ElementMapAccess::new(self.de, self.start, fields)) } fn deserialize_enum( diff --git a/src/de/mod.rs b/src/de/mod.rs index 7671985b..fab4915d 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -2815,34 +2815,31 @@ where fn skip(&mut self) -> Result<(), DeError> { let event = self.next()?; self.skip_event(event)?; - match self.write.back() { - // Skip all subtree, if we skip a start event - Some(DeEvent::Start(e)) => { - let end = e.name().as_ref().to_owned(); - let mut depth = 0; - loop { - let event = self.next()?; - match event { - DeEvent::Start(ref e) if e.name().as_ref() == end => { - self.skip_event(event)?; - depth += 1; - } - DeEvent::End(ref e) if e.name().as_ref() == end => { - self.skip_event(event)?; - if depth == 0 { - break; - } - depth -= 1; - } - DeEvent::Eof => { - self.skip_event(event)?; + // Skip all subtree, if we skip a start event + if let Some(DeEvent::Start(e)) = self.write.back() { + let end = e.name().as_ref().to_owned(); + let mut depth = 0; + loop { + let event = self.next()?; + match event { + DeEvent::Start(ref e) if e.name().as_ref() == end => { + self.skip_event(event)?; + depth += 1; + } + DeEvent::End(ref e) if e.name().as_ref() == end => { + self.skip_event(event)?; + if depth == 0 { break; } - _ => self.skip_event(event)?, + depth -= 1; + } + DeEvent::Eof => { + self.skip_event(event)?; + break; } + _ => self.skip_event(event)?, } } - _ => (), } Ok(()) } @@ -3214,7 +3211,7 @@ where } } -impl<'de, 'a, R, E> de::Deserializer<'de> for &'a mut Deserializer<'de, R, E> +impl<'de, R, E> de::Deserializer<'de> for &mut Deserializer<'de, R, E> where R: XmlRead<'de>, E: EntityResolver, @@ -3235,7 +3232,7 @@ where // When document is pretty-printed there could be whitespaces before the root element self.skip_whitespaces()?; match self.next()? { - DeEvent::Start(e) => visitor.visit_map(ElementMapAccess::new(self, e, fields)?), + DeEvent::Start(e) => visitor.visit_map(ElementMapAccess::new(self, e, fields)), // SAFETY: The reader is guaranteed that we don't have unmatched tags // If we here, then our deserializer has a bug DeEvent::End(e) => unreachable!("{:?}", e), @@ -3330,7 +3327,7 @@ where DeEvent::Text(t) if t.is_empty() => visitor.visit_none(), DeEvent::Eof => visitor.visit_none(), // if the `xsi:nil` attribute is set to true we got a none value - DeEvent::Start(start) if self.reader.reader.has_nil_attr(&start) => { + DeEvent::Start(start) if self.reader.reader.has_nil_attr(start) => { self.skip_next_tree()?; visitor.visit_none() } @@ -3354,7 +3351,7 @@ where /// /// Technically, multiple top-level elements violates XML rule of only one top-level /// element, but we consider this as several concatenated XML documents. -impl<'de, 'a, R, E> SeqAccess<'de> for &'a mut Deserializer<'de, R, E> +impl<'de, R, E> SeqAccess<'de> for &mut Deserializer<'de, R, E> where R: XmlRead<'de>, E: EntityResolver, @@ -3381,7 +3378,7 @@ where } } -impl<'de, 'a, R, E> IntoDeserializer<'de, DeError> for &'a mut Deserializer<'de, R, E> +impl<'de, R, E> IntoDeserializer<'de, DeError> for &mut Deserializer<'de, R, E> where R: XmlRead<'de>, E: EntityResolver, @@ -4508,6 +4505,8 @@ mod tests { use super::*; /// ... + // The same name is intentional + #[allow(clippy::module_inception)] mod start { use super::*; use pretty_assertions::assert_eq; @@ -4980,6 +4979,8 @@ mod tests { } } + // The same name is intentional + #[allow(clippy::module_inception)] mod cdata { use super::*; use pretty_assertions::assert_eq; diff --git a/src/de/var.rs b/src/de/var.rs index b5544129..e64e29f8 100644 --- a/src/de/var.rs +++ b/src/de/var.rs @@ -132,7 +132,7 @@ where V: Visitor<'de>, { match self.de.next()? { - DeEvent::Start(e) => visitor.visit_map(ElementMapAccess::new(self.de, e, fields)?), + DeEvent::Start(e) => visitor.visit_map(ElementMapAccess::new(self.de, e, fields)), DeEvent::Text(e) => { SimpleTypeDeserializer::from_text_content(e).deserialize_struct("", fields, visitor) } diff --git a/src/encoding.rs b/src/encoding.rs index 1de73605..d894f950 100644 --- a/src/encoding.rs +++ b/src/encoding.rs @@ -248,6 +248,8 @@ pub fn decode_into( /// |`3C 3F 78 6D`|UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns for the relevant ASCII characters, the encoding declaration itself may be read reliably #[cfg(feature = "encoding")] pub fn detect_encoding(bytes: &[u8]) -> Option<(&'static Encoding, usize)> { + // Prevent suggesting " Some((UTF_16BE, 2)), diff --git a/src/escape.rs b/src/escape.rs index 5656025f..a0fc6a38 100644 --- a/src/escape.rs +++ b/src/escape.rs @@ -2183,7 +2183,8 @@ mod normalization { if ch == '\u{0085}' { assert_eq!(normalize_xml11_eols(input), "\n", "{}", description); } else { - let mut expected = utf8.clone(); + // utf8 is copied, because [u8; 3] implements Copy + let mut expected = utf8; expected[0] = b'\n'; let expected = std::str::from_utf8(&expected).expect(&description); assert_eq!(normalize_xml11_eols(input), expected, "{}", description); diff --git a/src/events/attributes.rs b/src/events/attributes.rs index f98fefb3..8e5b88bb 100644 --- a/src/events/attributes.rs +++ b/src/events/attributes.rs @@ -432,7 +432,7 @@ impl<'a> Attributes<'a> { impl<'a> Debug for Attributes<'a> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.debug_struct("Attributes") - .field("bytes", &Bytes(&self.bytes)) + .field("bytes", &Bytes(self.bytes)) .field("state", &self.state) .field("decoder", &self.decoder) .finish() diff --git a/src/events/mod.rs b/src/events/mod.rs index f7a0ee59..64d676bf 100644 --- a/src/events/mod.rs +++ b/src/events/mod.rs @@ -358,12 +358,12 @@ impl<'a> arbitrary::Arbitrary<'a> for BytesStart<'a> { return Err(arbitrary::Error::IncorrectFormat); } let mut result = Self::new(s); - result.extend_attributes(Vec::<(&str, &str)>::arbitrary(u)?.into_iter()); + result.extend_attributes(Vec::<(&str, &str)>::arbitrary(u)?); Ok(result) } fn size_hint(depth: usize) -> (usize, Option) { - return <&str as arbitrary::Arbitrary>::size_hint(depth); + <&str as arbitrary::Arbitrary>::size_hint(depth) } } @@ -483,7 +483,7 @@ impl<'a> arbitrary::Arbitrary<'a> for BytesEnd<'a> { Ok(Self::new(<&str>::arbitrary(u)?)) } fn size_hint(depth: usize) -> (usize, Option) { - return <&str as arbitrary::Arbitrary>::size_hint(depth); + <&str as arbitrary::Arbitrary>::size_hint(depth) } } @@ -692,7 +692,7 @@ impl<'a> arbitrary::Arbitrary<'a> for BytesText<'a> { } fn size_hint(depth: usize) -> (usize, Option) { - return <&str as arbitrary::Arbitrary>::size_hint(depth); + <&str as arbitrary::Arbitrary>::size_hint(depth) } } @@ -976,7 +976,7 @@ impl<'a> arbitrary::Arbitrary<'a> for BytesCData<'a> { Ok(Self::new(<&str>::arbitrary(u)?)) } fn size_hint(depth: usize) -> (usize, Option) { - return <&str as arbitrary::Arbitrary>::size_hint(depth); + <&str as arbitrary::Arbitrary>::size_hint(depth) } } @@ -1062,7 +1062,7 @@ impl<'a> BytesPI<'a> { #[inline] pub fn into_owned(self) -> BytesPI<'static> { BytesPI { - content: self.content.into_owned().into(), + content: self.content.into_owned(), } } @@ -1171,7 +1171,7 @@ impl<'a> arbitrary::Arbitrary<'a> for BytesPI<'a> { Ok(Self::new(<&str>::arbitrary(u)?)) } fn size_hint(depth: usize) -> (usize, Option) { - return <&str as arbitrary::Arbitrary>::size_hint(depth); + <&str as arbitrary::Arbitrary>::size_hint(depth) } } @@ -1456,7 +1456,7 @@ impl<'a> arbitrary::Arbitrary<'a> for BytesDecl<'a> { } fn size_hint(depth: usize) -> (usize, Option) { - return <&str as arbitrary::Arbitrary>::size_hint(depth); + <&str as arbitrary::Arbitrary>::size_hint(depth) } } diff --git a/src/lib.rs b/src/lib.rs index afc4c149..068c2b5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,7 +50,8 @@ // Enable feature requirements in the docs from 1.57 // See https://stackoverflow.com/questions/61417452 // docs.rs defines `docsrs` when building documentation -#![cfg_attr(docsrs, feature(doc_auto_cfg))] +// Since 1.92 `doc_auto_cfg` was merged into `doc_cfg` +#![cfg_attr(docsrs, feature(doc_cfg))] #[cfg(feature = "serialize")] pub mod de; diff --git a/src/name.rs b/src/name.rs index dc16dd0c..a3d3f41a 100644 --- a/src/name.rs +++ b/src/name.rs @@ -609,7 +609,7 @@ impl NamespaceResolver { match prefix { PrefixDeclaration::Default => { let start = self.buffer.len(); - self.buffer.extend_from_slice(&namespace.0); + self.buffer.extend_from_slice(namespace.0); self.bindings.push(NamespaceBinding { start, prefix_len: 0, @@ -640,7 +640,7 @@ impl NamespaceResolver { let start = self.buffer.len(); self.buffer.extend_from_slice(prefix); - self.buffer.extend_from_slice(&namespace.0); + self.buffer.extend_from_slice(namespace.0); self.bindings.push(NamespaceBinding { start, prefix_len: prefix.len(), @@ -662,9 +662,8 @@ impl NamespaceResolver { // (default namespace) attribute. for a in start.attributes().with_checks(false) { if let Ok(Attribute { key: k, value: v }) = a { - match k.as_namespace_binding() { - Some(prefix) => self.add(prefix, Namespace(&v))?, - None => {} + if let Some(prefix) = k.as_namespace_binding() { + self.add(prefix, Namespace(&v))?; } } else { break; diff --git a/src/reader/state.rs b/src/reader/state.rs index c5e6b7c7..656e57cc 100644 --- a/src/reader/state.rs +++ b/src/reader/state.rs @@ -156,7 +156,7 @@ impl ReaderState { // We want report error at place where name is expected - this is just // before `>` self.last_error_offset = self.offset - 1; - return Err(Error::IllFormed(IllFormedError::MissingDoctypeName)); + Err(Error::IllFormed(IllFormedError::MissingDoctypeName)) } } } @@ -239,7 +239,7 @@ impl ReaderState { /// /// Returns `Decl` or `PI` event pub fn emit_question_mark<'b>(&mut self, buf: &'b [u8]) -> Result> { - debug_assert!(buf.len() > 0); + debug_assert!(!buf.is_empty()); debug_assert_eq!(buf[0], b'?'); let len = buf.len(); diff --git a/src/se/element.rs b/src/se/element.rs index 2a1184db..3dea52aa 100644 --- a/src/se/element.rs +++ b/src/se/element.rs @@ -551,7 +551,7 @@ impl<'w, 'k, W: Write> SerializeMap for Map<'w, 'k, W> { where T: ?Sized + Serialize, { - if let Some(_) = self.key.take() { + if self.key.take().is_some() { return Err(SeError::Custom( "calling `serialize_key` twice without `serialize_value`".to_string(), )); diff --git a/src/se/mod.rs b/src/se/mod.rs index ac511157..1ac3782b 100644 --- a/src/se/mod.rs +++ b/src/se/mod.rs @@ -435,6 +435,8 @@ macro_rules! forward { /// /// const fn is_xml11_name_start_char(ch: char) -> bool { + // Not need to use macro when core primitives is enough + #[allow(clippy::match_like_matches_macro)] match ch { ':' | 'A'..='Z' @@ -467,7 +469,7 @@ const fn is_xml11_name_char(ch: char) -> bool { /// Helper struct to self-defense from errors #[derive(Clone, Copy, Debug, PartialEq)] -pub(self) struct XmlName<'n>(&'n str); +struct XmlName<'n>(&'n str); impl<'n> XmlName<'n> { /// Checks correctness of the XML name according to [XML 1.1 specification] @@ -638,7 +640,7 @@ impl<'w, 'r, W: Write> Serializer<'w, 'r, W> { allow_primitive: true, expand_empty_elements: false, }, - root_tag: root_tag.map(|tag| XmlName::try_from(tag)).transpose()?, + root_tag: root_tag.map(XmlName::try_from).transpose()?, }) } diff --git a/src/se/simple_type.rs b/src/se/simple_type.rs index 2eedb97b..4e07713b 100644 --- a/src/se/simple_type.rs +++ b/src/se/simple_type.rs @@ -61,7 +61,7 @@ where if let Some(part) = it.next() { writer.write_str(part)?; } - while let Some(part) = it.next() { + for part in it { writer.write_str("]]> Writer { /// Writes bytes #[inline] pub(crate) fn write(&mut self, value: &[u8]) -> io::Result<()> { - self.writer.write_all(value).map_err(Into::into) + self.writer.write_all(value) } #[inline] @@ -497,7 +497,7 @@ impl<'a, W> ElementWriter<'a, W> { self.spaces.resize(indent, b' '); } self.start_tag.push_indent(&self.spaces[..indent]); - self.start_tag.push_attr(attr.into()); + self.start_tag.push_attr(attr); AttributeIndent::Spaces(indent) } // .new_line() was not called, but .with_attribute() was. @@ -511,7 +511,7 @@ impl<'a, W> ElementWriter<'a, W> { // New line was already written AttributeIndent::WriteConfigured(indent) => { self.start_tag.push_indent(i.additional(indent)); - self.start_tag.push_attr(attr.into()); + self.start_tag.push_attr(attr); AttributeIndent::Configured(indent) } // .new_line() was not called, but .with_attribute() was. diff --git a/tests/issues.rs b/tests/issues.rs index d4fdcbb0..916ba7ff 100644 --- a/tests/issues.rs +++ b/tests/issues.rs @@ -182,9 +182,8 @@ fn issue590() { )); let mut buf = Vec::new(); loop { - match reader.read_event_into(&mut buf).unwrap() { - Event::Eof => break, - _ => (), + if reader.read_event_into(&mut buf).unwrap() == Event::Eof { + break; } } } diff --git a/tests/serde_helpers/mod.rs b/tests/serde_helpers/mod.rs index 0d5143ab..637e732b 100644 --- a/tests/serde_helpers/mod.rs +++ b/tests/serde_helpers/mod.rs @@ -17,7 +17,7 @@ where let result = T::deserialize(&mut de); // If type was deserialized, the whole XML document should be consumed - if let Ok(_) = result { + if result.is_ok() { de.check_eof_reached(); } diff --git a/tests/writer-indentation.rs b/tests/writer-indentation.rs index baabd967..4e23bbc6 100644 --- a/tests/writer-indentation.rs +++ b/tests/writer-indentation.rs @@ -9,7 +9,7 @@ fn self_closed() { let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4); let tag = BytesStart::new("self-closed") - .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter()); + .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")]); writer .write_event(Event::Empty(tag)) .expect("write tag failed"); @@ -25,8 +25,8 @@ fn empty_paired() { let mut buffer = Vec::new(); let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4); - let start = BytesStart::new("paired") - .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter()); + let start = + BytesStart::new("paired").with_attributes(vec![("attr1", "value1"), ("attr2", "value2")]); let end = start.to_end(); writer .write_event(Event::Start(start.clone())) @@ -47,8 +47,8 @@ fn paired_with_inner() { let mut buffer = Vec::new(); let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4); - let start = BytesStart::new("paired") - .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter()); + let start = + BytesStart::new("paired").with_attributes(vec![("attr1", "value1"), ("attr2", "value2")]); let end = start.to_end(); let inner = BytesStart::new("inner"); @@ -75,8 +75,8 @@ fn paired_with_text() { let mut buffer = Vec::new(); let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4); - let start = BytesStart::new("paired") - .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter()); + let start = + BytesStart::new("paired").with_attributes(vec![("attr1", "value1"), ("attr2", "value2")]); let end = start.to_end(); let text = BytesText::new("text"); @@ -101,8 +101,8 @@ fn mixed_content() { let mut buffer = Vec::new(); let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4); - let start = BytesStart::new("paired") - .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter()); + let start = + BytesStart::new("paired").with_attributes(vec![("attr1", "value1"), ("attr2", "value2")]); let end = start.to_end(); let text = BytesText::new("text"); let inner = BytesStart::new("inner"); @@ -132,8 +132,8 @@ fn nested() { let mut buffer = Vec::new(); let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4); - let start = BytesStart::new("paired") - .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter()); + let start = + BytesStart::new("paired").with_attributes(vec![("attr1", "value1"), ("attr2", "value2")]); let end = start.to_end(); let inner = BytesStart::new("inner"); @@ -199,8 +199,8 @@ fn serializable() { val: "foo".to_owned(), }; - let start = BytesStart::new("paired") - .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter()); + let start = + BytesStart::new("paired").with_attributes(vec![("attr1", "value1"), ("attr2", "value2")]); let end = start.to_end(); writer