final section parser
This commit is contained in:
parent
458d6517d1
commit
2b7b5664c1
7 changed files with 170 additions and 3 deletions
|
@ -15,10 +15,10 @@ use crate::fragments::whitespace::{fws, is_obs_no_ws_ctl};
|
|||
use crate::fragments::words::{atom, is_vchar};
|
||||
use crate::error::IMFError;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct Unstructured(pub String);
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct PhraseList(pub Vec<String>);
|
||||
|
||||
impl<'a> TryFrom<&'a lazy::Unstructured<'a>> for Unstructured {
|
||||
|
|
|
@ -15,6 +15,7 @@ mod trace;
|
|||
mod datetime;
|
||||
pub mod lazy;
|
||||
pub mod eager;
|
||||
pub mod section;
|
||||
|
||||
// Header blocks
|
||||
pub mod header;
|
||||
|
|
81
src/fragments/section.rs
Normal file
81
src/fragments/section.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use crate::fragments::model::{
|
||||
MailboxList, MailboxRef, AddressList,
|
||||
MessageId, MessageIdList, AddressRef};
|
||||
use crate::fragments::misc_token::{Unstructured, PhraseList};
|
||||
use crate::fragments::trace::ReceivedLog;
|
||||
use crate::fragments::eager::Field;
|
||||
use crate::fragments::lazy;
|
||||
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct Section<'a> {
|
||||
// 3.6.1. The Origination Date Field
|
||||
pub date: Option<DateTime<FixedOffset>>,
|
||||
|
||||
// 3.6.2. Originator Fields
|
||||
pub from: Vec<MailboxRef>,
|
||||
pub sender: Option<MailboxRef>,
|
||||
pub reply_to: Vec<AddressRef>,
|
||||
|
||||
// 3.6.3. Destination Address Fields
|
||||
pub to: Vec<AddressRef>,
|
||||
pub cc: Vec<AddressRef>,
|
||||
pub bcc: Vec<AddressRef>,
|
||||
|
||||
// 3.6.4. Identification Fields
|
||||
pub msg_id: Option<MessageId<'a>>,
|
||||
pub in_reply_to: Vec<MessageId<'a>>,
|
||||
pub references: Vec<MessageId<'a>>,
|
||||
|
||||
// 3.6.5. Informational Fields
|
||||
pub subject: Option<Unstructured>,
|
||||
pub comments: Vec<Unstructured>,
|
||||
pub keywords: Vec<PhraseList>,
|
||||
|
||||
// 3.6.6 Not implemented
|
||||
// 3.6.7 Trace Fields
|
||||
pub return_path: Vec<MailboxRef>,
|
||||
pub received: Vec<ReceivedLog<'a>>,
|
||||
|
||||
// 3.6.8. Optional Fields
|
||||
pub optional: HashMap<&'a str, Unstructured>,
|
||||
|
||||
// Recovery
|
||||
pub bad_fields: Vec<lazy::Field<'a>>,
|
||||
pub unparsed: Vec<&'a str>,
|
||||
}
|
||||
|
||||
//@FIXME min and max limits are not enforced,
|
||||
// it may result in missing data or silently overriden data.
|
||||
impl<'a> From<Vec<Field<'a>>> for Section<'a> {
|
||||
fn from(field_list: Vec<Field<'a>>) -> Self {
|
||||
field_list.into_iter().fold(
|
||||
Section::default(),
|
||||
|mut section, field| {
|
||||
match field {
|
||||
Field::Date(v) => section.date = Some(v),
|
||||
Field::From(v) => section.from.extend(v),
|
||||
Field::Sender(v) => section.sender = Some(v),
|
||||
Field::ReplyTo(v) => section.reply_to.extend(v),
|
||||
Field::To(v) => section.to.extend(v),
|
||||
Field::Cc(v) => section.cc.extend(v),
|
||||
Field::Bcc(v) => section.bcc.extend(v),
|
||||
Field::MessageID(v) => section.msg_id = Some(v),
|
||||
Field::InReplyTo(v) => section.in_reply_to.extend(v),
|
||||
Field::References(v) => section.references.extend(v),
|
||||
Field::Subject(v) => section.subject = Some(v),
|
||||
Field::Comments(v) => section.comments.push(v),
|
||||
Field::Keywords(v) => section.keywords.push(v),
|
||||
Field::ReturnPath(v) => section.return_path.push(v),
|
||||
Field::Received(v) => section.received.push(v),
|
||||
Field::Optional(k, v) => { section.optional.insert(k, v); },
|
||||
Field::Rescue(v) => section.unparsed.push(v),
|
||||
};
|
||||
section
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ mod tests {
|
|||
use chrono::{FixedOffset, TimeZone};
|
||||
|
||||
#[test]
|
||||
fn test_field_name() {
|
||||
fn test_field_body() {
|
||||
assert_eq!(Parsed::from(&field_lazy::Parsed {
|
||||
fields: vec![
|
||||
lazy::Field::From(lazy::MailboxList("hello@world.com,\r\n\talice@wonderlands.com\r\n")),
|
||||
|
|
84
src/multipass/header_section.rs
Normal file
84
src/multipass/header_section.rs
Normal file
|
@ -0,0 +1,84 @@
|
|||
use crate::fragments::section::Section;
|
||||
use crate::multipass::field_eager;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Parsed<'a> {
|
||||
pub fields: Section<'a>,
|
||||
pub body: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> From<field_eager::Parsed<'a>> for Parsed<'a> {
|
||||
fn from(p: field_eager::Parsed<'a>) -> Self {
|
||||
Parsed {
|
||||
fields: p.fields.into(),
|
||||
body: p.body,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::fragments::eager;
|
||||
use crate::fragments::model;
|
||||
use chrono::{FixedOffset, TimeZone};
|
||||
|
||||
#[test]
|
||||
fn test_section() {
|
||||
assert_eq!(Parsed::from(field_eager::Parsed {
|
||||
fields: vec![
|
||||
eager::Field::From(vec![
|
||||
model::MailboxRef {
|
||||
name: None,
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "hello".into(),
|
||||
domain: "world.com".into()
|
||||
}
|
||||
},
|
||||
model::MailboxRef {
|
||||
name: None,
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "alice".into(),
|
||||
domain: "wonderlands.com".into()
|
||||
}
|
||||
},
|
||||
]),
|
||||
eager::Field::Date(
|
||||
FixedOffset::east_opt(0)
|
||||
.unwrap()
|
||||
.with_ymd_and_hms(1997, 03, 12, 7, 33, 25)
|
||||
.unwrap()
|
||||
),
|
||||
],
|
||||
body: b"Hello world!",
|
||||
}),
|
||||
Parsed {
|
||||
fields: Section {
|
||||
from: vec![
|
||||
model::MailboxRef {
|
||||
name: None,
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "hello".into(),
|
||||
domain: "world.com".into()
|
||||
}
|
||||
},
|
||||
model::MailboxRef {
|
||||
name: None,
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "alice".into(),
|
||||
domain: "wonderlands.com".into()
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
date: Some(FixedOffset::east_opt(0)
|
||||
.unwrap()
|
||||
.with_ymd_and_hms(1997, 03, 12, 7, 33, 25)
|
||||
.unwrap()),
|
||||
|
||||
..Default::default()
|
||||
},
|
||||
body: b"Hello world!",
|
||||
});
|
||||
}
|
||||
}
|
|
@ -3,3 +3,4 @@ pub mod guess_charset;
|
|||
pub mod extract_fields;
|
||||
pub mod field_lazy;
|
||||
pub mod field_eager;
|
||||
pub mod header_section;
|
||||
|
|
Loading…
Reference in a new issue