refactor imf parsing

This commit is contained in:
Quentin 2023-08-30 11:35:46 +02:00
parent ba59b037ef
commit dfb5b9fe0f
Signed by: quentin
GPG key ID: E9602264D639FF68
3 changed files with 74 additions and 65 deletions

View file

@ -6,14 +6,13 @@ use nom::{
IResult, IResult,
}; };
use crate::header::{field_name, header}; use crate::header::{field_name};
use crate::imf::address::{address_list, mailbox_list, nullable_address_list, AddressList}; use crate::imf::address::{address_list, mailbox_list, nullable_address_list, AddressList};
use crate::imf::datetime::section as date; use crate::imf::datetime::section as date;
use crate::imf::identification::{msg_id, msg_list, MessageID, MessageIDList}; use crate::imf::identification::{msg_id, msg_list, MessageID, MessageIDList};
use crate::imf::mailbox::{mailbox, AddrSpec, MailboxList, MailboxRef}; use crate::imf::mailbox::{mailbox, AddrSpec, MailboxList, MailboxRef};
use crate::imf::mime::{version, Version}; use crate::imf::mime::{version, Version};
use crate::imf::trace::{received_log, return_path, ReceivedLog}; use crate::imf::trace::{received_log, return_path, ReceivedLog};
use crate::imf::Imf;
use crate::text::misc_token::{phrase_list, unstructured, PhraseList, Unstructured}; use crate::text::misc_token::{phrase_list, unstructured, PhraseList, Unstructured};
use crate::text::whitespace::obs_crlf; use crate::text::whitespace::obs_crlf;
@ -49,6 +48,9 @@ pub enum Field<'a> {
MIMEVersion(Version), MIMEVersion(Version),
} }
/*impl<'a> From<header::Field<'a>> for Field<'a> {
fn from(raw: header::Field
}*/
pub fn field(input: &[u8]) -> IResult<&[u8], Field> { pub fn field(input: &[u8]) -> IResult<&[u8], Field> {
terminated( terminated(
@ -79,64 +81,3 @@ pub fn field(input: &[u8]) -> IResult<&[u8], Field> {
obs_crlf, obs_crlf,
)(input) )(input)
} }
pub fn imf(input: &[u8]) -> IResult<&[u8], Imf> {
map(header(field), |(known, unknown, bad)| {
let mut imf = Imf::from_iter(known);
imf.header_ext = unknown;
imf.header_bad = bad;
imf
})(input)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::imf::address::*;
use crate::imf::mailbox::*;
use crate::text::misc_token::*;
use chrono::{FixedOffset, TimeZone};
#[test]
fn test_header() {
let fullmail = b"Date: 7 Mar 2023 08:00:00 +0200
From: someone@example.com
To: someone_else@example.com
Subject: An RFC 822 formatted message
This is the plain text body of the message. Note the blank line
between the header information and the body of the message.";
assert_eq!(
imf(fullmail),
Ok((
&b"This is the plain text body of the message. Note the blank line\nbetween the header information and the body of the message."[..],
Imf {
date: Some(FixedOffset::east_opt(2 * 3600).unwrap().with_ymd_and_hms(2023, 3, 7, 8, 0, 0).unwrap()),
from: vec![MailboxRef {
name: None,
addrspec: AddrSpec {
local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(&b"someone"[..]))]),
domain: Domain::Atoms(vec![&b"example"[..], &b"com"[..]]),
}
}],
to: vec![AddressRef::Single(MailboxRef {
name: None,
addrspec: AddrSpec {
local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(&b"someone_else"[..]))]),
domain: Domain::Atoms(vec![&b"example"[..], &b"com"[..]]),
}
})],
subject: Some(Unstructured(vec![
UnstrToken::Plain(&b"An"[..]),
UnstrToken::Plain(&b"RFC"[..]),
UnstrToken::Plain(&b"822"[..]),
UnstrToken::Plain(&b"formatted"[..]),
UnstrToken::Plain(&b"message"[..]),
])),
..Imf::default()
}
)),
)
}
}

View file

@ -8,8 +8,14 @@ pub mod mailbox;
pub mod mime; pub mod mime;
pub mod trace; pub mod trace;
use nom::{
combinator::map,
IResult,
};
use crate::header::header;
use crate::imf::address::AddressRef; use crate::imf::address::AddressRef;
use crate::imf::field::Field; use crate::imf::field::{field, Field};
use crate::imf::identification::MessageID; use crate::imf::identification::MessageID;
use crate::imf::mailbox::{AddrSpec, MailboxRef}; use crate::imf::mailbox::{AddrSpec, MailboxRef};
use crate::imf::mime::Version; use crate::imf::mime::Version;
@ -92,3 +98,65 @@ impl<'a> FromIterator<Field<'a>> for Imf<'a> {
}) })
} }
} }
pub fn imf(input: &[u8]) -> IResult<&[u8], Imf> {
map(header(field), |(known, unknown, bad)| {
let mut imf = Imf::from_iter(known);
imf.header_ext = unknown;
imf.header_bad = bad;
imf
})(input)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::imf::address::*;
use crate::imf::mailbox::*;
use crate::text::misc_token::*;
use chrono::{FixedOffset, TimeZone};
#[test]
fn test_header() {
let fullmail = b"Date: 7 Mar 2023 08:00:00 +0200
From: someone@example.com
To: someone_else@example.com
Subject: An RFC 822 formatted message
This is the plain text body of the message. Note the blank line
between the header information and the body of the message.";
assert_eq!(
imf(fullmail),
Ok((
&b"This is the plain text body of the message. Note the blank line\nbetween the header information and the body of the message."[..],
Imf {
date: Some(FixedOffset::east_opt(2 * 3600).unwrap().with_ymd_and_hms(2023, 3, 7, 8, 0, 0).unwrap()),
from: vec![MailboxRef {
name: None,
addrspec: AddrSpec {
local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(&b"someone"[..]))]),
domain: Domain::Atoms(vec![&b"example"[..], &b"com"[..]]),
}
}],
to: vec![AddressRef::Single(MailboxRef {
name: None,
addrspec: AddrSpec {
local_part: LocalPart(vec![LocalPartToken::Word(Word::Atom(&b"someone_else"[..]))]),
domain: Domain::Atoms(vec![&b"example"[..], &b"com"[..]]),
}
})],
subject: Some(Unstructured(vec![
UnstrToken::Plain(&b"An"[..]),
UnstrToken::Plain(&b"RFC"[..]),
UnstrToken::Plain(&b"822"[..]),
UnstrToken::Plain(&b"formatted"[..]),
UnstrToken::Plain(&b"message"[..]),
])),
..Imf::default()
}
)),
)
}
}

View file

@ -98,5 +98,5 @@ pub fn parse_message(input: &[u8]) -> IResult<&[u8], part::composite::Message> {
/// ); /// );
/// ``` /// ```
pub fn parse_imf(input: &[u8]) -> IResult<&[u8], imf::Imf> { pub fn parse_imf(input: &[u8]) -> IResult<&[u8], imf::Imf> {
imf::field::imf(input) imf::imf(input)
} }