From b4e8b99b221dec592174dc8e570aa1a249c1650b Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Sun, 23 Jul 2023 17:14:16 +0200 Subject: [PATCH] more debug --- Cargo.lock | 34 +++++++++++----------------------- Cargo.toml | 9 ++++----- src/parse.rs | 30 ++++-------------------------- src/part/part.rs | 23 +++++++++++++++++++++-- src/rfc5322/mailbox.rs | 27 +++++++++++++++++++-------- src/text/misc_token.rs | 38 +++++++++++++++++++++++++++----------- 6 files changed, 86 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fcfc840..10a78bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -47,17 +47,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chardetng" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b8f0b65b7b08ae3c8187e8d77174de20cb6777864c6b832d8ad365999cf1ea" -dependencies = [ - "cfg-if", - "encoding_rs", - "memchr", -] - [[package]] name = "chrono" version = "0.4.26" @@ -79,6 +68,17 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "eml-codec" +version = "0.1.0" +dependencies = [ + "base64", + "chrono", + "encoding_rs", + "nom", + "walkdir", +] + [[package]] name = "encoding_rs" version = "0.8.32" @@ -111,18 +111,6 @@ dependencies = [ "cc", ] -[[package]] -name = "imf-codec" -version = "0.1.0" -dependencies = [ - "base64", - "chardetng", - "chrono", - "encoding_rs", - "nom", - "walkdir", -] - [[package]] name = "js-sys" version = "0.3.63" diff --git a/Cargo.toml b/Cargo.toml index 80a2e71..aee5e6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "imf-codec" +name = "eml-codec" version = "0.1.0" edition = "2021" license = "GPL-3.0-or-later" @@ -7,20 +7,19 @@ license = "GPL-3.0-or-later" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] -name = "imf_codec" +name = "eml_codec" path = "src/lib.rs" [[bin]] -name = "imf_parse" +name = "eml_parse" path = "src/parse.rs" [dependencies] nom = "7" chrono = "0.4" -chardetng = "0.1" -encoding_rs = "0.8" base64 = "0.21" +encoding_rs = "0.8" [dev-dependencies] walkdir = "2" diff --git a/src/parse.rs b/src/parse.rs index 9f5407b..c8bb891 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -3,35 +3,13 @@ use std::io; use std::io::Read; -/* -fn parser<'a, F>(input: &'a [u8], func: F) -> () -where - F: FnOnce(&Section) -> (), -{ - let seg = segment::new(input).unwrap(); - let charset = seg.charset(); - let fields = charset.fields().unwrap(); - let field_names = fields.names(); - let field_body = field_names.body(); - let section = field_body.section(); - - func(§ion.fields); -}*/ - fn main() { - /* // Read full mail in memory let mut rawmail = Vec::new(); io::stdin().lock().read_to_end(&mut rawmail).unwrap(); - // Parse it - parser(&rawmail[..], |section| { - // Checks/debug - println!("{:?}", section); - assert!(section.date.is_some()); - assert!(section.from.len() > 0); - assert!(section.bad_fields.len() == 0); - }); - */ - println!("hello world"); + let eml = eml_codec::email(&rawmail).unwrap(); + println!("{:#?}", eml); + assert!(eml.1.date.is_some()); + assert!(eml.1.from.len() > 0); } diff --git a/src/part/part.rs b/src/part/part.rs index ef7fe5b..41a21c2 100644 --- a/src/part/part.rs +++ b/src/part/part.rs @@ -1,3 +1,4 @@ +use std::fmt; use nom::{ branch::alt, bytes::complete::is_not, @@ -25,11 +26,29 @@ pub struct Message<'a>( pub Box>, ); -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] pub struct Text<'a>(pub mime::mime::Text<'a>, pub &'a [u8]); +impl<'a> fmt::Debug for Text<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt + .debug_struct("part::Text") + .field("mime", &self.0) + .field("body", &format_args!("\"{}\"", String::from_utf8_lossy(self.1))) + .finish() + } +} -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] pub struct Binary<'a>(pub mime::mime::Binary<'a>, pub &'a [u8]); +impl<'a> fmt::Debug for Binary<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt + .debug_struct("part::Binary") + .field("mime", &self.0) + .field("body", &format_args!("\"{}\"", String::from_utf8_lossy(self.1))) + .finish() + } +} #[derive(Debug, PartialEq)] pub enum AnyPart<'a> { diff --git a/src/rfc5322/mailbox.rs b/src/rfc5322/mailbox.rs index 6087e7f..b8f80dd 100644 --- a/src/rfc5322/mailbox.rs +++ b/src/rfc5322/mailbox.rs @@ -1,3 +1,4 @@ +use std::fmt; use nom::{ branch::alt, bytes::complete::{tag, take_while1}, @@ -12,13 +13,13 @@ use crate::text::misc_token::{phrase, word, Phrase, Word}; use crate::text::whitespace::{cfws, fws, is_obs_no_ws_ctl}; use crate::text::words::atom; -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] pub struct AddrSpec<'a> { pub local_part: LocalPart<'a>, pub domain: Domain<'a>, } -impl<'a> AddrSpec<'a> { - pub fn to_string(&self) -> String { +impl<'a> ToString for AddrSpec<'a> { + fn to_string(&self) -> String { format!( "{}@{}", self.local_part.to_string(), @@ -26,6 +27,11 @@ impl<'a> AddrSpec<'a> { ) } } +impl<'a> fmt::Debug for AddrSpec<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("AddrSpec").field(&format_args!("\"{}\"", self.to_string())).finish() + } +} #[derive(Debug, PartialEq)] pub struct MailboxRef<'a> { @@ -33,8 +39,8 @@ pub struct MailboxRef<'a> { pub addrspec: AddrSpec<'a>, pub name: Option>, } -impl<'a> MailboxRef<'a> { - pub fn to_string(&self) -> String { +impl<'a> ToString for MailboxRef<'a> { + fn to_string(&self) -> String { match &self.name { Some(n) => format!("{} <{}>", n.to_string(), self.addrspec.to_string()), None => self.addrspec.to_string(), @@ -166,14 +172,14 @@ fn obs_local_part(input: &[u8]) -> IResult<&[u8], LocalPart> { )(input) } -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] pub enum Domain<'a> { Atoms(Vec<&'a [u8]>), Litteral(Vec<&'a [u8]>), } -impl<'a> Domain<'a> { - pub fn to_string(&self) -> String { +impl<'a> ToString for Domain<'a> { + fn to_string(&self) -> String { match self { Domain::Atoms(v) => v .iter() @@ -201,6 +207,11 @@ impl<'a> Domain<'a> { } } } +impl<'a> fmt::Debug for Domain<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Domain").field(&format_args!("\"{}\"", self.to_string())).finish() + } +} /// Obsolete domain /// diff --git a/src/text/misc_token.rs b/src/text/misc_token.rs index 1580a9c..039276d 100644 --- a/src/text/misc_token.rs +++ b/src/text/misc_token.rs @@ -1,3 +1,4 @@ +use std::fmt; use nom::{ branch::alt, bytes::complete::{tag, take_while1}, @@ -50,15 +51,15 @@ pub fn mime_word(input: &[u8]) -> IResult<&[u8], MIMEWord> { ))(input) } -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] pub enum Word<'a> { Quoted(QuotedString<'a>), Encoded(encoding::EncodedWord<'a>), Atom(&'a [u8]), } -impl<'a> Word<'a> { - pub fn to_string(&self) -> String { +impl<'a> ToString for Word<'a> { + fn to_string(&self) -> String { match self { Word::Quoted(v) => v.to_string(), Word::Encoded(v) => v.to_string(), @@ -69,6 +70,11 @@ impl<'a> Word<'a> { } } } +impl<'a> fmt::Debug for Word<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Word").field(&format_args!("\"{}\"", self.to_string())).finish() + } +} /// Word /// @@ -83,11 +89,11 @@ pub fn word(input: &[u8]) -> IResult<&[u8], Word> { ))(input) } -#[derive(Debug, PartialEq)] +#[derive(PartialEq)] pub struct Phrase<'a>(pub Vec>); -impl<'a> Phrase<'a> { - pub fn to_string(&self) -> String { +impl<'a> ToString for Phrase<'a> { + fn to_string(&self) -> String { self.0 .iter() .map(|v| v.to_string()) @@ -95,6 +101,11 @@ impl<'a> Phrase<'a> { .join(" ") } } +impl<'a> fmt::Debug for Phrase<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Phrase").field(&format_args!("\"{}\"", self.to_string())).finish() + } +} /// Phrase /// @@ -122,8 +133,8 @@ pub enum UnstrToken<'a> { Plain(&'a [u8]), } -impl<'a> UnstrToken<'a> { - pub fn to_string(&self) -> String { +impl<'a> ToString for UnstrToken<'a> { + fn to_string(&self) -> String { match self { UnstrToken::Init => "".into(), UnstrToken::Encoded(e) => e.to_string(), @@ -135,11 +146,11 @@ impl<'a> UnstrToken<'a> { } } -#[derive(Debug, PartialEq, Clone)] +#[derive(PartialEq, Clone)] pub struct Unstructured<'a>(pub Vec>); -impl<'a> Unstructured<'a> { - pub fn to_string(&self) -> String { +impl<'a> ToString for Unstructured<'a> { + fn to_string(&self) -> String { self.0 .iter() .fold( @@ -162,6 +173,11 @@ impl<'a> Unstructured<'a> { .1 } } +impl<'a> fmt::Debug for Unstructured<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_tuple("Unstructured").field(&format_args!("\"{}\"", self.to_string())).finish() + } +} /// Unstructured header field body ///