From 4109b509dbf81f6bb98426895034b95b97d7e301 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 21 Oct 2024 10:52:08 +0200 Subject: [PATCH 01/12] Move multipart classification into own closure --- src/parsers/message.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index fdce5106..6a59c1d3 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -326,6 +326,7 @@ impl MessageParser { let is_html = mime_type == MimeType::TextHtml; + let mut classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| { if add_to_html && !is_html { message.html_body.push(message.parts.len()); } else if add_to_text && is_html { @@ -339,6 +340,9 @@ impl MessageParser { } else { message.attachments.push(message.parts.len()); } + }; + + classifier(add_to_html, is_html, add_to_text); if is_html { PartType::Html(text) From 7eba962668bd19bb8d80c0cf4606d7f11bfe5b40 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 21 Oct 2024 10:56:05 +0200 Subject: [PATCH 02/12] Add classification enum --- src/parsers/message.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index 6a59c1d3..354ed160 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -326,7 +326,8 @@ impl MessageParser { let is_html = mime_type == MimeType::TextHtml; - let mut classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| { + let mut classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| -> Vec { + let mut add_to = Vec::new(); if add_to_html && !is_html { message.html_body.push(message.parts.len()); } else if add_to_text && is_html { @@ -340,8 +341,17 @@ impl MessageParser { } else { message.attachments.push(message.parts.len()); } + add_to.sort(); + add_to }; + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] + enum Class { + Html, + Text, + Attachment, + } + classifier(add_to_html, is_html, add_to_text); if is_html { From b99504a605a753f8d0ed73d274913314ccce3a62 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 14:04:49 +0200 Subject: [PATCH 03/12] Express classification indirectly with an enum --- src/parsers/message.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index 354ed160..1a0078c0 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -329,17 +329,17 @@ impl MessageParser { let mut classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| -> Vec { let mut add_to = Vec::new(); if add_to_html && !is_html { - message.html_body.push(message.parts.len()); + add_to.push(Class::Html); } else if add_to_text && is_html { - message.text_body.push(message.parts.len()); + add_to.push(Class::Text); } if add_to_html && is_html { - message.html_body.push(message.parts.len()); + add_to.push(Class::Html); } else if add_to_text && !is_html { - message.text_body.push(message.parts.len()); + add_to.push(Class::Text); } else { - message.attachments.push(message.parts.len()); + add_to.push(Class::Attachment); } add_to.sort(); add_to @@ -352,7 +352,13 @@ impl MessageParser { Attachment, } - classifier(add_to_html, is_html, add_to_text); + for add_to in classifier(add_to_html, is_html, add_to_text) { + match add_to { + Class::Html => message.html_body.push(message.parts.len()), + Class::Text => message.text_body.push(message.parts.len()), + Class::Attachment => message.attachments.push(message.parts.len()), + } + } if is_html { PartType::Html(text) From 53cd15ebd1f509b6de0762739fb82a8db012cca3 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 14:14:54 +0200 Subject: [PATCH 04/12] Express logic clause in equivalent way, add assert inline test to make sure of it --- src/parsers/message.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index 1a0078c0..9fbf1f56 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -345,6 +345,30 @@ impl MessageParser { add_to }; + let alt_classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| -> Vec { + let mut add_to = Vec::new(); + if add_to_text { + add_to.push(Class::Text); + } + if add_to_html { + add_to.push(Class::Html); + } + if !add_to_html && is_html || !add_to_text && !is_html { + add_to.push(Class::Attachment); + } + add_to.sort(); + add_to + }; + + // classifiers are identical + for f1 in [false, true] { + for f2 in [false, true] { + for f3 in [false, true] { + assert_eq!(classifier(f1, f2, f3), alt_classifier(f1, f2, f3)); + } + } + } + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] enum Class { Html, From fe1c67d1c2e824ab7c176277d307fde24cf469c7 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 14:17:54 +0200 Subject: [PATCH 05/12] Remove old classifier --- src/parsers/message.rs | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index 9fbf1f56..54d96b7f 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -326,25 +326,6 @@ impl MessageParser { let is_html = mime_type == MimeType::TextHtml; - let mut classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| -> Vec { - let mut add_to = Vec::new(); - if add_to_html && !is_html { - add_to.push(Class::Html); - } else if add_to_text && is_html { - add_to.push(Class::Text); - } - - if add_to_html && is_html { - add_to.push(Class::Html); - } else if add_to_text && !is_html { - add_to.push(Class::Text); - } else { - add_to.push(Class::Attachment); - } - add_to.sort(); - add_to - }; - let alt_classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| -> Vec { let mut add_to = Vec::new(); if add_to_text { @@ -360,15 +341,6 @@ impl MessageParser { add_to }; - // classifiers are identical - for f1 in [false, true] { - for f2 in [false, true] { - for f3 in [false, true] { - assert_eq!(classifier(f1, f2, f3), alt_classifier(f1, f2, f3)); - } - } - } - #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] enum Class { Html, @@ -376,7 +348,7 @@ impl MessageParser { Attachment, } - for add_to in classifier(add_to_html, is_html, add_to_text) { + for add_to in alt_classifier(add_to_html, is_html, add_to_text) { match add_to { Class::Html => message.html_body.push(message.parts.len()), Class::Text => message.text_body.push(message.parts.len()), From dd392727663cd3f17540883b5bdbcbf6a296eb4e Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 14:21:29 +0200 Subject: [PATCH 06/12] Remove enum indirection --- src/parsers/message.rs | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index 54d96b7f..cd1622e6 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -326,35 +326,19 @@ impl MessageParser { let is_html = mime_type == MimeType::TextHtml; - let alt_classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| -> Vec { - let mut add_to = Vec::new(); + let mut alt_classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| { if add_to_text { - add_to.push(Class::Text); + message.text_body.push(message.parts.len()); } if add_to_html { - add_to.push(Class::Html); + message.html_body.push(message.parts.len()); } if !add_to_html && is_html || !add_to_text && !is_html { - add_to.push(Class::Attachment); + message.attachments.push(message.parts.len()); } - add_to.sort(); - add_to }; - #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] - enum Class { - Html, - Text, - Attachment, - } - - for add_to in alt_classifier(add_to_html, is_html, add_to_text) { - match add_to { - Class::Html => message.html_body.push(message.parts.len()), - Class::Text => message.text_body.push(message.parts.len()), - Class::Attachment => message.attachments.push(message.parts.len()), - } - } + alt_classifier(add_to_html, is_html, add_to_text); if is_html { PartType::Html(text) From 6377bd0d825d88e0ebc2350247af06223b767fab Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 14:23:00 +0200 Subject: [PATCH 07/12] Remove closure --- src/parsers/message.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index cd1622e6..249d9de7 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -326,19 +326,15 @@ impl MessageParser { let is_html = mime_type == MimeType::TextHtml; - let mut alt_classifier = |add_to_html: bool, is_html: bool, add_to_text: bool| { - if add_to_text { - message.text_body.push(message.parts.len()); - } - if add_to_html { - message.html_body.push(message.parts.len()); - } - if !add_to_html && is_html || !add_to_text && !is_html { - message.attachments.push(message.parts.len()); - } - }; - - alt_classifier(add_to_html, is_html, add_to_text); + if add_to_text { + message.text_body.push(message.parts.len()); + } + if add_to_html { + message.html_body.push(message.parts.len()); + } + if !add_to_html && is_html || !add_to_text && !is_html { + message.attachments.push(message.parts.len()); + } if is_html { PartType::Html(text) From ea00cf78405365f5d41e97164a020a3617d862a0 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 14:32:33 +0200 Subject: [PATCH 08/12] Hoist common if condition into outer scope --- src/parsers/message.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index 249d9de7..e00b1566 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -306,6 +306,13 @@ impl MessageParser { (false, false) }; + if add_to_html { + message.html_body.push(message.parts.len()); + } + if add_to_text { + message.text_body.push(message.parts.len()); + } + if is_text { let text = match ( bytes, @@ -326,12 +333,6 @@ impl MessageParser { let is_html = mime_type == MimeType::TextHtml; - if add_to_text { - message.text_body.push(message.parts.len()); - } - if add_to_html { - message.html_body.push(message.parts.len()); - } if !add_to_html && is_html || !add_to_text && !is_html { message.attachments.push(message.parts.len()); } @@ -342,13 +343,6 @@ impl MessageParser { PartType::Text(text) } } else { - if add_to_html { - message.html_body.push(message.parts.len()); - } - if add_to_text { - message.text_body.push(message.parts.len()); - } - message.attachments.push(message.parts.len()); if !is_inline { From d382c5343b67dfe2e761c23f9d8b87e92aaafe00 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 15:05:31 +0200 Subject: [PATCH 09/12] Simplify expression --- src/core/header.rs | 2 +- src/parsers/message.rs | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/core/header.rs b/src/core/header.rs index ec4b2cae..805aa7c9 100644 --- a/src/core/header.rs +++ b/src/core/header.rs @@ -804,7 +804,7 @@ impl<'x> ContentType<'x> { pub fn has_attribute(&self, name: &str) -> bool { self.attributes .as_ref() - .map_or_else(|| false, |attr| attr.iter().any(|(key, _)| key == name)) + .map_or(false, |attr| attr.iter().any(|(key, _)| key == name)) } /// Returns ```true``` if the Content-Disposition type is "attachment" diff --git a/src/parsers/message.rs b/src/parsers/message.rs index e00b1566..8de61f27 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -163,9 +163,7 @@ impl MessageParser { mime_type(content_type, &state.mime_type); if is_multipart { - if let Some(mime_boundary) = - content_type.map_or_else(|| None, |f| f.attribute("boundary")) - { + if let Some(mime_boundary) = content_type.and_then(|f| f.attribute("boundary")) { if stream.seek_next_part(mime_boundary.as_bytes()) { let part_id = message.parts.len(); let new_state = MessageParserState { @@ -272,15 +270,13 @@ impl MessageParser { let is_inline = is_inline && part_headers .header_value(&HeaderName::ContentDisposition) - .map_or_else( - || true, - |d| !d.as_content_type().map_or(false, |ct| ct.is_attachment()), - ) + .map_or(true, |d| { + !d.as_content_type().map_or(false, |ct| ct.is_attachment()) + }) && (state.parts == 1 - || (state.mime_type != MimeType::MultipartRelated + || state.mime_type != MimeType::MultipartRelated && (mime_type == MimeType::Inline - || content_type - .map_or_else(|| true, |c| !c.has_attribute("name"))))); + || content_type.map_or(true, |c| !c.has_attribute("name")))); let (add_to_html, add_to_text) = if let MimeType::MultipartAlternative = state.mime_type { From 76016c368aa1f2ef633cb5cb759715ba1eabb10f Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 17:41:56 +0200 Subject: [PATCH 10/12] Simplify lifetime bounds A missing lifetime in the GetHeader trait was inferred by lifetime elision rules to be shorter than necessary, leading to awkward lifetime constraints being propagated throughout many functions that didnt need them. --- src/core/address.rs | 2 +- src/core/header.rs | 6 +++--- src/core/message.rs | 26 +++++++++++++------------- src/lib.rs | 4 ++-- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/core/address.rs b/src/core/address.rs index 5f2633c5..90f52e0e 100644 --- a/src/core/address.rs +++ b/src/core/address.rs @@ -73,7 +73,7 @@ impl<'x> Address<'x> { } /// Returns an iterator over the addresses in the list, or the addresses in the groups. - pub fn iter<'y: 'x>(&'y self) -> Box> + 'x> { + pub fn iter(&self) -> Box> + '_> { match self { Address::List(list) => Box::new(list.iter()), Address::Group(group) => { diff --git a/src/core/header.rs b/src/core/header.rs index 805aa7c9..6403da4c 100644 --- a/src/core/header.rs +++ b/src/core/header.rs @@ -374,7 +374,7 @@ impl<'x> HeaderName<'x> { } } - pub fn as_str<'y: 'x>(&'y self) -> &'x str { + pub fn as_str(&self) -> &str { match self { HeaderName::Other(other) => other.as_ref(), _ => self.as_static_str(), @@ -921,14 +921,14 @@ impl<'x> Host<'x> { } impl<'x> GetHeader<'x> for Vec> { - fn header_value(&self, name: &HeaderName) -> Option<&HeaderValue<'x>> { + fn header_value(&self, name: &HeaderName<'_>) -> Option<&HeaderValue<'x>> { self.iter() .rev() .find(|header| &header.name == name) .map(|header| &header.value) } - fn header(&self, name: impl Into>) -> Option<&Header> { + fn header(&self, name: impl Into>) -> Option<&Header<'x>> { let name = name.into(); self.iter().rev().find(|header| header.name == name) } diff --git a/src/core/message.rs b/src/core/message.rs index 58336695..ed959085 100644 --- a/src/core/message.rs +++ b/src/core/message.rs @@ -90,8 +90,8 @@ impl<'x> Message<'x> { } /// Returns an iterator over the matching RFC headers of this message. - pub fn header_values<'y: 'x>( - &'y self, + pub fn header_values( + &self, name: impl Into>, ) -> impl Iterator> { let name = name.into(); @@ -124,7 +124,7 @@ impl<'x> Message<'x> { } /// Returns the BCC header field - pub fn bcc<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn bcc(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::Bcc) @@ -132,7 +132,7 @@ impl<'x> Message<'x> { } /// Returns the CC header field - pub fn cc<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn cc(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::Cc) @@ -156,7 +156,7 @@ impl<'x> Message<'x> { } /// Returns the From header field - pub fn from<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn from(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::From) @@ -268,7 +268,7 @@ impl<'x> Message<'x> { } /// Returns the Reply-To header field - pub fn reply_to<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn reply_to(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::ReplyTo) @@ -276,7 +276,7 @@ impl<'x> Message<'x> { } /// Returns the Resent-BCC header field - pub fn resent_bcc<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn resent_bcc(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::ResentBcc) @@ -284,7 +284,7 @@ impl<'x> Message<'x> { } /// Returns the Resent-CC header field - pub fn resent_cc<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn resent_cc(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::ResentTo) @@ -300,7 +300,7 @@ impl<'x> Message<'x> { } /// Returns the Resent-From header field - pub fn resent_from<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn resent_from(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::ResentFrom) @@ -316,7 +316,7 @@ impl<'x> Message<'x> { } /// Returns the Sender header field - pub fn resent_sender<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn resent_sender(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::ResentSender) @@ -324,7 +324,7 @@ impl<'x> Message<'x> { } /// Returns the Resent-To header field - pub fn resent_to<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn resent_to(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::ResentTo) @@ -353,7 +353,7 @@ impl<'x> Message<'x> { } /// Returns the Sender header field - pub fn sender<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn sender(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::Sender) @@ -375,7 +375,7 @@ impl<'x> Message<'x> { } /// Returns the To header field - pub fn to<'y: 'x>(&'y self) -> Option<&Address<'x>> { + pub fn to(&self) -> Option<&Address<'x>> { self.parts[0] .headers .header_value(&HeaderName::To) diff --git a/src/lib.rs b/src/lib.rs index 220936f7..aa530863 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -649,8 +649,8 @@ pub trait MimeHeaders<'x> { } pub trait GetHeader<'x> { - fn header_value(&self, name: &HeaderName) -> Option<&HeaderValue>; - fn header(&self, name: impl Into>) -> Option<&Header>; + fn header_value(&self, name: &HeaderName<'_>) -> Option<&HeaderValue<'x>>; + fn header(&self, name: impl Into>) -> Option<&Header<'x>>; } #[doc(hidden)] From 4751478f6e6f94ec6ec4e9526c796f2c88b12cd2 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 14 Oct 2024 18:10:49 +0200 Subject: [PATCH 11/12] Prohibit Rust 2018 idioms, return longest feasible lifetimes --- src/core/header.rs | 34 +++++++++++----------- src/core/message.rs | 46 +++++++++++++++--------------- src/decoders/encoded_word.rs | 2 +- src/lib.rs | 7 +++-- src/mailbox/maildir.rs | 2 +- src/parsers/fields/content_type.rs | 2 +- src/parsers/fields/date.rs | 2 +- src/parsers/header.rs | 2 +- src/parsers/message.rs | 4 +-- 9 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/core/header.rs b/src/core/header.rs index 6403da4c..49f0a137 100644 --- a/src/core/header.rs +++ b/src/core/header.rs @@ -26,7 +26,7 @@ impl<'x> Header<'x> { } /// Returns the parsed header value - pub fn value(&self) -> &HeaderValue { + pub fn value(&self) -> &HeaderValue<'x> { &self.value } @@ -171,14 +171,14 @@ impl<'x> HeaderValue<'x> { } } - pub fn as_received(&self) -> Option<&Received> { + pub fn as_received(&self) -> Option<&Received<'x>> { match *self { HeaderValue::Received(ref r) => Some(r), _ => None, } } - pub fn as_content_type(&self) -> Option<&ContentType> { + pub fn as_content_type(&self) -> Option<&ContentType<'x>> { match *self { HeaderValue::ContentType(ref c) => Some(c), _ => None, @@ -542,7 +542,7 @@ impl<'x> MimeHeaders<'x> for Message<'x> { .and_then(|header| header.as_text()) } - fn content_disposition(&self) -> Option<&ContentType> { + fn content_disposition(&self) -> Option<&ContentType<'x>> { self.parts[0] .headers .header_value(&HeaderName::ContentDisposition) @@ -563,14 +563,14 @@ impl<'x> MimeHeaders<'x> for Message<'x> { .and_then(|header| header.as_text()) } - fn content_type(&self) -> Option<&ContentType> { + fn content_type(&self) -> Option<&ContentType<'x>> { self.parts[0] .headers .header_value(&HeaderName::ContentType) .and_then(|header| header.as_content_type()) } - fn content_language(&self) -> &HeaderValue { + fn content_language(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ContentLanguage) @@ -667,7 +667,7 @@ impl<'x> MessagePart<'x> { } /// Get the message headers - pub fn headers(&self) -> &[Header] { + pub fn headers(&self) -> &[Header<'x>] { &self.headers } @@ -713,7 +713,7 @@ impl<'x> MessagePart<'x> { } impl<'x> fmt::Display for MessagePart<'x> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.write_str(self.text_contents().unwrap_or("[no contents]")) } } @@ -725,7 +725,7 @@ impl<'x> MimeHeaders<'x> for MessagePart<'x> { .and_then(|header| header.as_text()) } - fn content_disposition(&self) -> Option<&ContentType> { + fn content_disposition(&self) -> Option<&ContentType<'x>> { self.headers .header_value(&HeaderName::ContentDisposition) .and_then(|header| header.as_content_type()) @@ -743,13 +743,13 @@ impl<'x> MimeHeaders<'x> for MessagePart<'x> { .and_then(|header| header.as_text()) } - fn content_type(&self) -> Option<&ContentType> { + fn content_type(&self) -> Option<&ContentType<'x>> { self.headers .header_value(&HeaderName::ContentType) .and_then(|header| header.as_content_type()) } - fn content_language(&self) -> &HeaderValue { + fn content_language(&self) -> &HeaderValue<'x> { self.headers .header_value(&HeaderName::ContentLanguage) .unwrap_or(&HeaderValue::Empty) @@ -786,7 +786,7 @@ impl<'x> ContentType<'x> { } /// Removes an attribute by name - pub fn remove_attribute(&mut self, name: &str) -> Option> { + pub fn remove_attribute(&mut self, name: &str) -> Option> { let attributes = self.attributes.as_mut()?; attributes @@ -796,7 +796,7 @@ impl<'x> ContentType<'x> { } /// Returns all attributes - pub fn attributes(&self) -> Option<&[(Cow, Cow)]> { + pub fn attributes(&self) -> Option<&[(Cow<'x, str>, Cow<'x, str>)]> { self.attributes.as_deref() } @@ -840,7 +840,7 @@ impl<'x> Received<'x> { } /// Returns the hostname or IP address of the machine that originated the message - pub fn from(&self) -> Option<&Host> { + pub fn from(&self) -> Option<&Host<'x>> { self.from.as_ref() } @@ -855,7 +855,7 @@ impl<'x> Received<'x> { } /// Returns the hostname or IP address of the machine that received the message - pub fn by(&self) -> Option<&Host> { + pub fn by(&self) -> Option<&Host<'x>> { self.by.as_ref() } @@ -890,7 +890,7 @@ impl<'x> Received<'x> { } /// Returns the EHLO/LHLO/HELO hostname or IP address of the machine that sent the message - pub fn helo(&self) -> Option<&Host> { + pub fn helo(&self) -> Option<&Host<'x>> { self.helo.as_ref() } @@ -953,7 +953,7 @@ impl<'x> From for HeaderName<'x> { } impl From> for String { - fn from(header: HeaderName) -> Self { + fn from(header: HeaderName<'_>) -> Self { header.to_string() } } diff --git a/src/core/message.rs b/src/core/message.rs index ed959085..e4c0a588 100644 --- a/src/core/message.rs +++ b/src/core/message.rs @@ -29,12 +29,12 @@ impl<'x> Message<'x> { } /// Returns a parsed header. - pub fn header(&self, header: impl Into>) -> Option<&HeaderValue> { + pub fn header(&self, header: impl Into>) -> Option<&HeaderValue<'x>> { self.parts[0].headers.header(header).map(|h| &h.value) } /// Removed a parsed header and returns its value. - pub fn remove_header(&mut self, header: impl Into>) -> Option { + pub fn remove_header(&mut self, header: impl Into>) -> Option> { let header = header.into(); let headers = &mut self.parts[0].headers; headers @@ -56,7 +56,7 @@ impl<'x> Message<'x> { &self, header: impl Into>, form: HeaderForm, - ) -> Vec { + ) -> Vec> { let header = header.into(); let mut results = Vec::new(); for header_ in &self.parts[0].headers { @@ -85,7 +85,7 @@ impl<'x> Message<'x> { } /// Returns an iterator over the RFC headers of this message. - pub fn headers(&self) -> &[Header] { + pub fn headers(&self) -> &[Header<'x>] { &self.parts[0].headers } @@ -140,7 +140,7 @@ impl<'x> Message<'x> { } /// Returns all Comments header fields - pub fn comments(&self) -> &HeaderValue { + pub fn comments(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::Comments) @@ -164,7 +164,7 @@ impl<'x> Message<'x> { } /// Returns all In-Reply-To header fields - pub fn in_reply_to(&self) -> &HeaderValue { + pub fn in_reply_to(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::InReplyTo) @@ -172,7 +172,7 @@ impl<'x> Message<'x> { } /// Returns all Keywords header fields - pub fn keywords(&self) -> &HeaderValue { + pub fn keywords(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::Keywords) @@ -180,7 +180,7 @@ impl<'x> Message<'x> { } /// Returns the List-Archive header field - pub fn list_archive(&self) -> &HeaderValue { + pub fn list_archive(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ListArchive) @@ -188,7 +188,7 @@ impl<'x> Message<'x> { } /// Returns the List-Help header field - pub fn list_help(&self) -> &HeaderValue { + pub fn list_help(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ListHelp) @@ -196,7 +196,7 @@ impl<'x> Message<'x> { } /// Returns the List-ID header field - pub fn list_id(&self) -> &HeaderValue { + pub fn list_id(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ListId) @@ -204,7 +204,7 @@ impl<'x> Message<'x> { } /// Returns the List-Owner header field - pub fn list_owner(&self) -> &HeaderValue { + pub fn list_owner(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ListOwner) @@ -212,7 +212,7 @@ impl<'x> Message<'x> { } /// Returns the List-Post header field - pub fn list_post(&self) -> &HeaderValue { + pub fn list_post(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ListPost) @@ -220,7 +220,7 @@ impl<'x> Message<'x> { } /// Returns the List-Subscribe header field - pub fn list_subscribe(&self) -> &HeaderValue { + pub fn list_subscribe(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ListSubscribe) @@ -228,7 +228,7 @@ impl<'x> Message<'x> { } /// Returns the List-Unsubscribe header field - pub fn list_unsubscribe(&self) -> &HeaderValue { + pub fn list_unsubscribe(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ListUnsubscribe) @@ -244,7 +244,7 @@ impl<'x> Message<'x> { } /// Returns the MIME-Version header field - pub fn mime_version(&self) -> &HeaderValue { + pub fn mime_version(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::MimeVersion) @@ -252,7 +252,7 @@ impl<'x> Message<'x> { } /// Returns the first Received header field - pub fn received(&self) -> Option<&Received> { + pub fn received(&self) -> Option<&Received<'x>> { self.parts[0] .headers .header_value(&HeaderName::Received) @@ -260,7 +260,7 @@ impl<'x> Message<'x> { } /// Returns all References header fields - pub fn references(&self) -> &HeaderValue { + pub fn references(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::References) @@ -292,7 +292,7 @@ impl<'x> Message<'x> { } /// Returns all Resent-Date header fields - pub fn resent_date(&self) -> &HeaderValue { + pub fn resent_date(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ResentDate) @@ -308,7 +308,7 @@ impl<'x> Message<'x> { } /// Returns all Resent-Message-ID header fields - pub fn resent_message_id(&self) -> &HeaderValue { + pub fn resent_message_id(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ResentMessageId) @@ -332,7 +332,7 @@ impl<'x> Message<'x> { } /// Returns all Return-Path header fields - pub fn return_path(&self) -> &HeaderValue { + pub fn return_path(&self) -> &HeaderValue<'x> { self.parts[0] .headers .header_value(&HeaderName::ReturnPath) @@ -414,17 +414,17 @@ impl<'x> Message<'x> { } /// Returns a message part by position - pub fn part(&self, pos: usize) -> Option<&MessagePart> { + pub fn part(&self, pos: usize) -> Option<&MessagePart<'x>> { self.parts.get(pos) } /// Returns an inline HTML body part by position - pub fn html_part(&self, pos: usize) -> Option<&MessagePart> { + pub fn html_part(&self, pos: usize) -> Option<&MessagePart<'x>> { self.parts.get(*self.html_body.get(pos)?) } /// Returns an inline text body part by position - pub fn text_part(&self, pos: usize) -> Option<&MessagePart> { + pub fn text_part(&self, pos: usize) -> Option<&MessagePart<'x>> { self.parts.get(*self.text_body.get(pos)?) } diff --git a/src/decoders/encoded_word.rs b/src/decoders/encoded_word.rs index f7287f2d..435df12a 100644 --- a/src/decoders/encoded_word.rs +++ b/src/decoders/encoded_word.rs @@ -26,7 +26,7 @@ impl<'x> MessageStream<'x> { let mut charset_start = 0; let mut charset_end = 0; - let mut decode_fnc: Option = None; + let mut decode_fnc: Option> = None; while let Some(ch) = self.next() { match state { diff --git a/src/lib.rs b/src/lib.rs index aa530863..3336e673 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![deny(rust_2018_idioms)] /* * Copyright Stalwart Labs Ltd. See the COPYING * file at the top-level directory of this distribution. @@ -619,15 +620,15 @@ pub trait MimeHeaders<'x> { /// Returns the Content-Description field fn content_description(&self) -> Option<&str>; /// Returns the Content-Disposition field - fn content_disposition(&self) -> Option<&ContentType>; + fn content_disposition(&self) -> Option<&ContentType<'_>>; /// Returns the Content-ID field fn content_id(&self) -> Option<&str>; /// Returns the Content-Encoding field fn content_transfer_encoding(&self) -> Option<&str>; /// Returns the Content-Type field - fn content_type(&self) -> Option<&ContentType>; + fn content_type(&self) -> Option<&ContentType<'_>>; /// Returns the Content-Language field - fn content_language(&self) -> &HeaderValue; + fn content_language(&self) -> &HeaderValue<'_>; /// Returns the Content-Location field fn content_location(&self) -> Option<&str>; /// Returns the attachment name, if any. diff --git a/src/mailbox/maildir.rs b/src/mailbox/maildir.rs index fec77f21..3f2cf05c 100644 --- a/src/mailbox/maildir.rs +++ b/src/mailbox/maildir.rs @@ -56,7 +56,7 @@ impl FolderIterator<'_> { pub fn new( path: impl Into, sub_folder_prefix: Option<&str>, - ) -> io::Result { + ) -> io::Result> { let path = path.into(); Ok(FolderIterator { diff --git a/src/parsers/fields/content_type.rs b/src/parsers/fields/content_type.rs index c02cb17a..f690f46b 100644 --- a/src/parsers/fields/content_type.rs +++ b/src/parsers/fields/content_type.rs @@ -223,7 +223,7 @@ impl<'x> ContentTypeParser<'x> { self.reset_parser(); } - fn add_attr_position(&mut self, stream: &MessageStream) -> bool { + fn add_attr_position(&mut self, stream: &MessageStream<'_>) -> bool { if self.token_start > 0 { self.attr_position = String::from_utf8_lossy(&stream.data[self.token_start - 1..self.token_end]) diff --git a/src/parsers/fields/date.rs b/src/parsers/fields/date.rs index b174dfc3..08ef672b 100644 --- a/src/parsers/fields/date.rs +++ b/src/parsers/fields/date.rs @@ -282,7 +282,7 @@ impl Ord for DateTime { } impl fmt::Display for DateTime { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.write_str(&self.to_rfc3339()) } } diff --git a/src/parsers/header.rs b/src/parsers/header.rs index e0e1b576..7b59638e 100644 --- a/src/parsers/header.rs +++ b/src/parsers/header.rs @@ -242,7 +242,7 @@ static HDR_HASH: &[u8] = &[ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, ]; -static HDR_MAP: &[HeaderName] = &[ +static HDR_MAP: &[HeaderName<'_>] = &[ HeaderName::Date, HeaderName::MimeVersion, // Invalid HeaderName::Sender, diff --git a/src/parsers/message.rs b/src/parsers/message.rs index 8de61f27..606c8a67 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -38,7 +38,7 @@ enum MimeType { #[inline(always)] fn mime_type( - content_type: Option<&ContentType>, + content_type: Option<&ContentType<'_>>, parent_content_type: &MimeType, ) -> (bool, bool, bool, MimeType) { if let Some(content_type) = content_type { @@ -199,7 +199,7 @@ impl MessageParser { } } - let (mut encoding, decode_fnc): (Encoding, DecodeFnc) = match part_headers + let (mut encoding, decode_fnc): (Encoding, DecodeFnc<'_>) = match part_headers .header_value(&HeaderName::ContentTransferEncoding) { Some(HeaderValue::Text(encoding)) if encoding.eq_ignore_ascii_case("base64") => { From cf7657da3755d9ab555e3785f1f914f1ffa73442 Mon Sep 17 00:00:00 2001 From: c Date: Mon, 21 Oct 2024 14:08:40 +0200 Subject: [PATCH 12/12] Dont duplicate crlf in extension when saving failing results --- src/parsers/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parsers/message.rs b/src/parsers/message.rs index 606c8a67..6a56b83b 100644 --- a/src/parsers/message.rs +++ b/src/parsers/message.rs @@ -626,7 +626,7 @@ mod tests { let json_message = serde_json::to_string_pretty(&message).unwrap(); if json_message.as_bytes() != expected_result { - file_name.set_extension("crlf.failed"); + file_name.set_extension("failed"); fs::write(&file_name, json_message.as_bytes()).unwrap(); panic!( "Test failed, parsed message saved to {}",