simplify content type structs
This commit is contained in:
parent
a8ae9c3714
commit
5df9b253ec
10 changed files with 26 additions and 692 deletions
|
@ -43,41 +43,41 @@ pub fn parameter_list(input: &[u8]) -> IResult<&[u8], Vec<Parameter>> {
|
|||
#[derive(Debug, PartialEq)]
|
||||
pub enum Type {
|
||||
// Composite types
|
||||
Multipart(MultipartDesc),
|
||||
Message(MessageSubtype),
|
||||
Multipart(Multipart),
|
||||
Message(Message),
|
||||
|
||||
// Discrete types
|
||||
Text(TextDesc),
|
||||
Text(Text),
|
||||
Binary,
|
||||
}
|
||||
impl Default for Type {
|
||||
fn default() -> Self {
|
||||
Self::Text(TextDesc::default())
|
||||
Self::Text(Text::default())
|
||||
}
|
||||
}
|
||||
impl<'a> From<&'a NaiveType<'a>> for Type {
|
||||
fn from(nt: &'a NaiveType<'a>) -> Self {
|
||||
match nt.main.to_ascii_lowercase().as_slice() {
|
||||
b"multipart" => MultipartDesc::try_from(nt).map(Self::Multipart).unwrap_or(Self::default()),
|
||||
b"message" => Self::Message(MessageSubtype::from(nt)),
|
||||
b"text" => Self::Text(TextDesc::from(nt)),
|
||||
b"multipart" => Multipart::try_from(nt).map(Self::Multipart).unwrap_or(Self::default()),
|
||||
b"message" => Self::Message(Message::from(nt)),
|
||||
b"text" => Self::Text(Text::from(nt)),
|
||||
_ => Self::Binary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct MultipartDesc {
|
||||
pub struct Multipart {
|
||||
pub subtype: MultipartSubtype,
|
||||
pub boundary: String,
|
||||
}
|
||||
impl<'a> TryFrom<&'a NaiveType<'a>> for MultipartDesc {
|
||||
impl<'a> TryFrom<&'a NaiveType<'a>> for Multipart {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(nt: &'a NaiveType<'a>) -> Result<Self, Self::Error> {
|
||||
nt.params.iter()
|
||||
.find(|x| x.name.to_ascii_lowercase().as_slice() == b"boundary")
|
||||
.map(|boundary| MultipartDesc {
|
||||
.map(|boundary| Multipart {
|
||||
subtype: MultipartSubtype::from(nt),
|
||||
boundary: boundary.value.to_string(),
|
||||
})
|
||||
|
@ -108,13 +108,13 @@ impl<'a> From<&NaiveType<'a>> for MultipartSubtype {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum MessageSubtype {
|
||||
pub enum Message {
|
||||
RFC822,
|
||||
Partial,
|
||||
External,
|
||||
Unknown,
|
||||
}
|
||||
impl<'a> From<&NaiveType<'a>> for MessageSubtype {
|
||||
impl<'a> From<&NaiveType<'a>> for Message {
|
||||
fn from(nt: &NaiveType<'a>) -> Self {
|
||||
match nt.sub.to_ascii_lowercase().as_slice() {
|
||||
b"rfc822" => Self::RFC822,
|
||||
|
@ -126,13 +126,13 @@ impl<'a> From<&NaiveType<'a>> for MessageSubtype {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct TextDesc {
|
||||
pub struct Text {
|
||||
pub subtype: TextSubtype,
|
||||
pub charset: EmailCharset,
|
||||
}
|
||||
impl<'a> From<&NaiveType<'a>> for TextDesc {
|
||||
impl<'a> From<&NaiveType<'a>> for Text {
|
||||
fn from(nt: &NaiveType<'a>) -> Self {
|
||||
TextDesc {
|
||||
Self {
|
||||
subtype: TextSubtype::from(nt),
|
||||
charset: nt.params.iter()
|
||||
.find(|x| x.name.to_ascii_lowercase().as_slice() == b"charset")
|
||||
|
@ -189,7 +189,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
nt.to_type(),
|
||||
Type::Text(TextDesc {
|
||||
Type::Text(Text {
|
||||
charset: EmailCharset::UTF_8,
|
||||
subtype: TextSubtype::Plain,
|
||||
})
|
||||
|
@ -203,7 +203,7 @@ mod tests {
|
|||
assert_eq!(rest, &[]);
|
||||
assert_eq!(
|
||||
nt.to_type(),
|
||||
Type::Multipart(MultipartDesc {
|
||||
Type::Multipart(Multipart {
|
||||
subtype: MultipartSubtype::Mixed,
|
||||
boundary: "--==_mimepart_64a3f2c69114f_2a13d020975fe".into(),
|
||||
})
|
||||
|
@ -217,7 +217,7 @@ mod tests {
|
|||
|
||||
assert_eq!(
|
||||
nt.to_type(),
|
||||
Type::Message(MessageSubtype::RFC822),
|
||||
Type::Message(Message::RFC822),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
use crate::fragments::part;
|
||||
use crate::fragments::section::Section;
|
||||
use crate::multipass::header_section;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Parsed<'a> {
|
||||
pub fields: Section<'a>,
|
||||
pub body: part::PartNode<'a>,
|
||||
}
|
||||
|
||||
pub fn new<'a>(p: &'a header_section::Parsed<'a>) -> Parsed<'a> {
|
||||
todo!();
|
||||
/*Parsed {
|
||||
fields: p.fields,
|
||||
body: p.body,
|
||||
}*/
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
use nom::{
|
||||
bytes::complete::is_not,
|
||||
character::complete::space1,
|
||||
combinator::{all_consuming, recognize},
|
||||
multi::{many0, many1},
|
||||
sequence::{pair, tuple},
|
||||
IResult,
|
||||
};
|
||||
|
||||
use crate::error::IMFError;
|
||||
use crate::fragments::fields;
|
||||
use crate::multipass::field_lazy;
|
||||
use crate::multipass::guess_charset;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Parsed<'a> {
|
||||
pub fields: Vec<&'a str>,
|
||||
pub body: &'a [u8],
|
||||
}
|
||||
|
||||
pub fn new<'a>(gcha: &'a guess_charset::Parsed<'a>) -> Result<Parsed<'a>, IMFError<'a>> {
|
||||
fields(&gcha.header)
|
||||
.map_err(|e| IMFError::ExtractFields(e))
|
||||
.map(|(_, fields)| Parsed {
|
||||
fields,
|
||||
body: gcha.body,
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a> Parsed<'a> {
|
||||
pub fn names(&'a self) -> field_lazy::Parsed<'a> {
|
||||
field_lazy::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_extract() {
|
||||
assert_eq!(
|
||||
new(&guess_charset::Parsed {
|
||||
header: "From: hello@world.com,\r\n\talice@wonderlands.com\r\nDate: 12 Mar 1997 07:33:25 Z\r\n".into(),
|
||||
encoding: encoding_rs::UTF_8,
|
||||
malformed: false,
|
||||
body: b"Hello world!",
|
||||
}),
|
||||
Ok(Parsed {
|
||||
fields: vec![
|
||||
"From: hello@world.com,\r\n\talice@wonderlands.com\r\n",
|
||||
"Date: 12 Mar 1997 07:33:25 Z\r\n",
|
||||
],
|
||||
body: b"Hello world!",
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,336 +0,0 @@
|
|||
use crate::fragments::eager;
|
||||
use crate::multipass::field_lazy;
|
||||
use crate::multipass::header_section;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Parsed<'a> {
|
||||
pub fields: Vec<eager::Field<'a>>,
|
||||
pub body: &'a [u8],
|
||||
}
|
||||
|
||||
pub fn new<'a>(p: &'a field_lazy::Parsed<'a>) -> Parsed<'a> {
|
||||
Parsed {
|
||||
fields: p
|
||||
.fields
|
||||
.iter()
|
||||
.filter_map(|entry| entry.try_into().ok())
|
||||
.collect(),
|
||||
body: p.body,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Parsed<'a> {
|
||||
pub fn section(&'a self) -> header_section::Parsed<'a> {
|
||||
header_section::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::fragments::lazy;
|
||||
use crate::fragments::model;
|
||||
use chrono::{FixedOffset, TimeZone};
|
||||
|
||||
#[test]
|
||||
fn test_field_body() {
|
||||
assert_eq!(
|
||||
new(&field_lazy::Parsed {
|
||||
fields: vec![
|
||||
lazy::Field::From(lazy::MailboxList(
|
||||
"hello@world.com,\r\n\talice@wonderlands.com\r\n"
|
||||
)),
|
||||
lazy::Field::Date(lazy::DateTime("12 Mar 1997 07:33:25 Z\r\n")),
|
||||
],
|
||||
body: b"Hello world!",
|
||||
}),
|
||||
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!",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
use crate::fragments::misc_token;
|
||||
use crate::multipass::extract_fields;
|
||||
fn lazy_eager<F>(input: &str, func: F)
|
||||
where
|
||||
F: Fn(&eager::Field),
|
||||
{
|
||||
let field = extract_fields::Parsed {
|
||||
fields: vec![input],
|
||||
body: b"",
|
||||
};
|
||||
let lazy = field_lazy::new(&field);
|
||||
let eager = new(&lazy);
|
||||
func(eager.fields.first().unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from() {
|
||||
lazy_eager(
|
||||
"From: \"Joe Q. Public\" <john.q.public@example.com>\r\n",
|
||||
|from| {
|
||||
assert_eq!(
|
||||
from,
|
||||
&eager::Field::From(vec![model::MailboxRef {
|
||||
name: Some("Joe Q. Public".into()),
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "john.q.public".into(),
|
||||
domain: "example.com".into(),
|
||||
}
|
||||
}])
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sender() {
|
||||
lazy_eager(
|
||||
"Sender: Michael Jones <mjones@machine.example>\r\n",
|
||||
|sender| {
|
||||
assert_eq!(
|
||||
sender,
|
||||
&eager::Field::Sender(model::MailboxRef {
|
||||
name: Some("Michael Jones".into()),
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "mjones".into(),
|
||||
domain: "machine.example".into(),
|
||||
},
|
||||
})
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reply_to() {
|
||||
lazy_eager(
|
||||
"Reply-To: \"Mary Smith: Personal Account\" <smith@home.example>\r\n",
|
||||
|reply_to| {
|
||||
assert_eq!(
|
||||
reply_to,
|
||||
&eager::Field::ReplyTo(vec![model::AddressRef::Single(model::MailboxRef {
|
||||
name: Some("Mary Smith: Personal Account".into()),
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "smith".into(),
|
||||
domain: "home.example".into(),
|
||||
},
|
||||
})])
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to() {
|
||||
lazy_eager(
|
||||
"To: A Group:Ed Jones <c@a.test>,joe@where.test,John <jdoe@one.test>;\r\n",
|
||||
|to| {
|
||||
assert_eq!(
|
||||
to,
|
||||
&eager::Field::To(vec![model::AddressRef::Many(model::GroupRef {
|
||||
name: "A Group".into(),
|
||||
participants: vec![
|
||||
model::MailboxRef {
|
||||
name: Some("Ed Jones".into()),
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "c".into(),
|
||||
domain: "a.test".into()
|
||||
},
|
||||
},
|
||||
model::MailboxRef {
|
||||
name: None,
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "joe".into(),
|
||||
domain: "where.test".into()
|
||||
},
|
||||
},
|
||||
model::MailboxRef {
|
||||
name: Some("John".into()),
|
||||
addrspec: model::AddrSpec {
|
||||
local_part: "jdoe".into(),
|
||||
domain: "one.test".into()
|
||||
},
|
||||
},
|
||||
]
|
||||
})])
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cc() {
|
||||
lazy_eager("Cc: Undisclosed recipients:;\r\n", |cc| {
|
||||
assert_eq!(
|
||||
cc,
|
||||
&eager::Field::Cc(vec![model::AddressRef::Many(model::GroupRef {
|
||||
name: "Undisclosed recipients".into(),
|
||||
participants: vec![],
|
||||
})]),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bcc() {
|
||||
lazy_eager("Bcc: (empty)\r\n", |bcc| {
|
||||
assert_eq!(bcc, &eager::Field::Bcc(vec![]),)
|
||||
});
|
||||
|
||||
lazy_eager("Bcc: \r\n", |bcc| {
|
||||
assert_eq!(bcc, &eager::Field::Bcc(vec![]),)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_message_id() {
|
||||
lazy_eager("Message-ID: <310@[127.0.0.1]>\r\n", |msg_id| {
|
||||
assert_eq!(
|
||||
msg_id,
|
||||
&eager::Field::MessageID(model::MessageId {
|
||||
left: "310",
|
||||
right: "127.0.0.1"
|
||||
},)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_in_reply_to() {
|
||||
lazy_eager("In-Reply-To: <a@b> <c@example.com>\r\n", |irt| {
|
||||
assert_eq!(
|
||||
irt,
|
||||
&eager::Field::InReplyTo(vec![
|
||||
model::MessageId {
|
||||
left: "a",
|
||||
right: "b"
|
||||
},
|
||||
model::MessageId {
|
||||
left: "c",
|
||||
right: "example.com"
|
||||
},
|
||||
])
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_references() {
|
||||
lazy_eager(
|
||||
"References: <1234@local.machine.example> <3456@example.net>\r\n",
|
||||
|refer| {
|
||||
assert_eq!(
|
||||
refer,
|
||||
&eager::Field::References(vec![
|
||||
model::MessageId {
|
||||
left: "1234",
|
||||
right: "local.machine.example"
|
||||
},
|
||||
model::MessageId {
|
||||
left: "3456",
|
||||
right: "example.net"
|
||||
},
|
||||
])
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subject() {
|
||||
lazy_eager("Subject: Aérogramme\r\n", |subject| {
|
||||
assert_eq!(
|
||||
subject,
|
||||
&eager::Field::Subject(misc_token::Unstructured("Aérogramme".into()))
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_comments() {
|
||||
lazy_eager("Comments: 😛 easter egg!\r\n", |comments| {
|
||||
assert_eq!(
|
||||
comments,
|
||||
&eager::Field::Comments(misc_token::Unstructured("😛 easter egg!".into())),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keywords() {
|
||||
lazy_eager(
|
||||
"Keywords: fantasque, farfelu, fanfreluche\r\n",
|
||||
|keywords| {
|
||||
assert_eq!(
|
||||
keywords,
|
||||
&eager::Field::Keywords(misc_token::PhraseList(vec![
|
||||
"fantasque".into(),
|
||||
"farfelu".into(),
|
||||
"fanfreluche".into()
|
||||
]))
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
//@FIXME non ported tests:
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn test_invalid_field_name() {
|
||||
assert!(known_field("Unknown: unknown\r\n").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rescue_field() {
|
||||
assert_eq!(
|
||||
rescue_field("Héron: élan\r\n\tnoël: test\r\nFrom: ..."),
|
||||
Ok(("From: ...", Field::Rescue("Héron: élan\r\n\tnoël: test"))),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrong_fields() {
|
||||
let fullmail = r#"Return-Path: xoxo
|
||||
From: !!!!
|
||||
|
||||
Hello world"#;
|
||||
assert_eq!(
|
||||
section(fullmail),
|
||||
Ok(("Hello world", HeaderSection {
|
||||
bad_fields: vec![
|
||||
Field::ReturnPath(FieldBody::Failed("xoxo")),
|
||||
Field::From(FieldBody::Failed("!!!!")),
|
||||
],
|
||||
..Default::default()
|
||||
}))
|
||||
);
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
use crate::fragments::lazy;
|
||||
use crate::multipass::extract_fields;
|
||||
use crate::multipass::field_eager;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Parsed<'a> {
|
||||
pub fields: Vec<lazy::Field<'a>>,
|
||||
pub body: &'a [u8],
|
||||
}
|
||||
|
||||
pub fn new<'a>(ef: &'a extract_fields::Parsed<'a>) -> Parsed<'a> {
|
||||
Parsed {
|
||||
fields: ef.fields.iter().map(|e| (*e).into()).collect(),
|
||||
body: ef.body,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Parsed<'a> {
|
||||
pub fn body(&'a self) -> field_eager::Parsed<'a> {
|
||||
field_eager::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_field_name() {
|
||||
assert_eq!(
|
||||
new(&extract_fields::Parsed {
|
||||
fields: vec![
|
||||
"From: hello@world.com,\r\n\talice@wonderlands.com\r\n",
|
||||
"Date: 12 Mar 1997 07:33:25 Z\r\n",
|
||||
],
|
||||
body: b"Hello world!",
|
||||
}),
|
||||
Parsed {
|
||||
fields: vec![
|
||||
lazy::Field::From(lazy::MailboxList(
|
||||
"hello@world.com,\r\n\talice@wonderlands.com\r\n"
|
||||
)),
|
||||
lazy::Field::Date(lazy::DateTime("12 Mar 1997 07:33:25 Z\r\n")),
|
||||
],
|
||||
body: b"Hello world!",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mime_fields() {
|
||||
assert_eq!(
|
||||
new(&extract_fields::Parsed {
|
||||
fields: vec![
|
||||
"MIME-Version: 1.0 \r\n",
|
||||
"Content-Type: multipart/alternative; boundary=\"bound\"\r\n",
|
||||
"Content-Transfer-Encoding: 7bit\r\n",
|
||||
"Content-ID: <foo4*foo1@bar.net>\r\n",
|
||||
"Content-Description: hello world\r\n",
|
||||
],
|
||||
body: b"Hello world!",
|
||||
}),
|
||||
Parsed {
|
||||
fields: vec![
|
||||
lazy::Field::MIMEVersion(lazy::Version("1.0 \r\n")),
|
||||
lazy::Field::MIME(lazy::MIMEField::ContentType(lazy::Type("multipart/alternative; boundary=\"bound\"\r\n"))),
|
||||
lazy::Field::MIME(lazy::MIMEField::ContentTransferEncoding(lazy::Mechanism("7bit\r\n"))),
|
||||
lazy::Field::MIME(lazy::MIMEField::ContentID(lazy::Identifier("<foo4*foo1@bar.net>\r\n"))),
|
||||
lazy::Field::MIME(lazy::MIMEField::ContentDescription(lazy::Unstructured("hello world\r\n"))),
|
||||
],
|
||||
body: b"Hello world!",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use crate::error::IMFError;
|
||||
use crate::fragments::encoding;
|
||||
use crate::multipass::extract_fields;
|
||||
use crate::multipass::segment;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Parsed<'a> {
|
||||
pub header: Cow<'a, str>,
|
||||
pub body: &'a [u8],
|
||||
}
|
||||
|
||||
pub fn new<'a>(seg: &'a segment::Parsed<'a>) -> Parsed<'a> {
|
||||
Parsed {
|
||||
header: encoding::header_decode(&seg.header),
|
||||
body: seg.body,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Parsed<'a> {
|
||||
pub fn fields(&'a self) -> Result<extract_fields::Parsed<'a>, IMFError<'a>> {
|
||||
extract_fields::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_charset() {
|
||||
assert_eq!(
|
||||
new(&segment::Parsed {
|
||||
body: b"Hello world!",
|
||||
header: b"From: hello@world.com\r\nDate: 12 Mar 1997 07:33:25 Z\r\n",
|
||||
}),
|
||||
Parsed {
|
||||
header: "From: hello@world.com\r\nDate: 12 Mar 1997 07:33:25 Z\r\n".into(),
|
||||
encoding: encoding_rs::UTF_8,
|
||||
malformed: false,
|
||||
body: b"Hello world!",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
use crate::fragments::section::Section;
|
||||
use crate::multipass::{field_eager, body_structure};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Parsed<'a> {
|
||||
pub fields: Section<'a>,
|
||||
pub body: &'a [u8],
|
||||
}
|
||||
|
||||
pub fn new<'a>(p: &'a field_eager::Parsed<'a>) -> Parsed<'a> {
|
||||
Parsed {
|
||||
fields: Section::from_iter(p.fields.iter()),
|
||||
body: p.body,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Parsed<'a> {
|
||||
pub fn body_structure(&self) -> body_structure::Parsed<'a> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::fragments::eager;
|
||||
use crate::fragments::model;
|
||||
use chrono::{FixedOffset, TimeZone};
|
||||
|
||||
#[test]
|
||||
fn test_section() {
|
||||
assert_eq!(
|
||||
new(&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!",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
pub mod extract_fields;
|
||||
pub mod field_eager;
|
||||
pub mod field_lazy;
|
||||
pub mod guess_charset;
|
||||
pub mod header_section;
|
||||
pub mod segment;
|
||||
pub mod body_structure;
|
|
@ -1,37 +0,0 @@
|
|||
use crate::error::IMFError;
|
||||
use crate::multipass::guess_charset;
|
||||
use crate::fragments::whitespace::headers;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Parsed<'a> {
|
||||
pub header: &'a [u8],
|
||||
pub body: &'a [u8],
|
||||
}
|
||||
|
||||
pub fn new<'a>(buffer: &'a [u8]) -> Result<Parsed<'a>, IMFError<'a>> {
|
||||
headers(buffer)
|
||||
.map_err(|e| IMFError::Segment(e))
|
||||
.map(|(body, header)| Parsed { header, body })
|
||||
}
|
||||
|
||||
impl<'a> Parsed<'a> {
|
||||
pub fn charset(&'a self) -> guess_charset::Parsed<'a> {
|
||||
guess_charset::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_segment() {
|
||||
assert_eq!(
|
||||
new(&b"From: hello@world.com\r\nDate: 12 Mar 1997 07:33:25 Z\r\n\r\nHello world!"[..]),
|
||||
Ok(Parsed {
|
||||
header: b"From: hello@world.com\r\nDate: 12 Mar 1997 07:33:25 Z\r\n",
|
||||
body: b"Hello world!",
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,12 +7,14 @@ use nom::{
|
|||
combinator::{not, opt, recognize},
|
||||
};
|
||||
|
||||
use crate::fragments::mime::{Mechanism, Type};
|
||||
use crate::fragments::model::MessageId;
|
||||
use crate::fragments::misc_token::Unstructured;
|
||||
use crate::fragments::whitespace::{CRLF, headers, line, obs_crlf};
|
||||
use crate::fragments::{eager,lazy};
|
||||
use crate::fragments::section::MIMESection;
|
||||
|
||||
pub struct Part<'a, T> {
|
||||
|
||||
}
|
||||
|
||||
impl<'a> Part<'a, r#type::Text<'a>> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue