some refactor
This commit is contained in:
parent
00d36fd498
commit
18b081cb9a
4 changed files with 100 additions and 50 deletions
|
@ -3,13 +3,12 @@ use nom::{
|
|||
branch::alt,
|
||||
bytes::complete::{tag_no_case, tag, take_while1},
|
||||
character::complete::space0,
|
||||
combinator::{not, map},
|
||||
combinator::{map},
|
||||
multi::many0,
|
||||
sequence::{pair, preceded, terminated, tuple},
|
||||
sequence::{pair, terminated, tuple},
|
||||
};
|
||||
use crate::text::whitespace::{foldable_line, obs_crlf};
|
||||
use crate::text::misc_token::{Unstructured, unstructured};
|
||||
use crate::text::boundary::boundary;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum CompField<'a, T> {
|
||||
|
@ -39,6 +38,7 @@ pub fn header<'a, T>(fx: impl Fn(&'a [u8]) -> IResult<&[u8], T> + Copy)
|
|||
))), obs_crlf), CompFieldList)(input)
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn header_in_boundaries<'a, T>(bound: &'a [u8], fx: impl Fn(&'a [u8]) -> IResult<&[u8], T> + Copy)
|
||||
-> impl Fn(&'a [u8]) -> IResult<&[u8], CompFieldList<T>>
|
||||
{
|
||||
|
@ -50,6 +50,7 @@ pub fn header_in_boundaries<'a, T>(bound: &'a [u8], fx: impl Fn(&'a [u8]) -> IRe
|
|||
map(foldable_line, CompField::Bad),
|
||||
)))), obs_crlf), CompFieldList)(input)
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn field_name<'a>(name: &'static [u8]) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
|
||||
move |input| {
|
||||
|
|
|
@ -2,21 +2,28 @@ use crate::mime::mechanism::Mechanism;
|
|||
use crate::rfc5322::identification::MessageID;
|
||||
use crate::text::misc_token::Unstructured;
|
||||
use crate::mime::field::Content;
|
||||
use crate::mime::r#type::{AnyType, Multipart, Message, Text, Binary};
|
||||
use crate::mime::r#type::{AnyType, self as ctype}; //Multipart, Message, Text, Binary};
|
||||
//
|
||||
pub struct Multipart<'a>(pub ctype::Multipart, Generic<'a>);
|
||||
pub struct Message<'a>(pub ctype::Message, Generic<'a>);
|
||||
pub struct Text<'a>(pub ctype::Text, Generic<'a>);
|
||||
pub struct Binary<'a>(pub ctype::Binary, Generic<'a>);
|
||||
|
||||
pub enum AnyMIME<'a> {
|
||||
Multipart(Multipart, Generic<'a>),
|
||||
Message(Message, Generic<'a>),
|
||||
Text(Text, Generic<'a>),
|
||||
Binary(Binary, Generic<'a>),
|
||||
Mult(Multipart<'a>),
|
||||
Msg(Message<'a>),
|
||||
Txt(Text<'a>),
|
||||
Bin(Binary<'a>),
|
||||
}
|
||||
|
||||
|
||||
impl<'a> AnyMIME<'a> {
|
||||
pub fn from_pair(at: AnyType, gen: Generic<'a>) -> Self {
|
||||
match at {
|
||||
AnyType::Multipart(m) => AnyMIME::Multipart(m, gen),
|
||||
AnyType::Message(m) => AnyMIME::Message(m, gen),
|
||||
AnyType::Text(m) => AnyMIME::Text(m, gen),
|
||||
AnyType::Binary(m) => AnyMIME::Binary(m, gen),
|
||||
AnyType::Multipart(m) => AnyMIME::Mult(Multipart(m, gen)),
|
||||
AnyType::Message(m) => AnyMIME::Msg(Message(m, gen)),
|
||||
AnyType::Text(m) => AnyMIME::Txt(Text(m, gen)),
|
||||
AnyType::Binary(m) => AnyMIME::Bin(Binary(m, gen)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
1
src/part/mod.rs
Normal file
1
src/part/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod part;
|
117
src/part/part.rs
117
src/part/part.rs
|
@ -7,65 +7,105 @@ use nom::{
|
|||
combinator::{not, opt, recognize},
|
||||
};
|
||||
|
||||
use crate::mime::r#type;
|
||||
use crate::mime::r#type as ctype;
|
||||
use crate::mime::mime;
|
||||
use crate::rfc5322::{self as imf};
|
||||
|
||||
pub struct Part<'a> {
|
||||
Multipart(Multipart<MIME>, Vec<Part<'a>>),
|
||||
Message(MIME<Message>, Message, Part<'a>),
|
||||
Text(MIME<Text>, &'a [u8]),
|
||||
Binary(MIME<Binary>, &'a [u8]),
|
||||
pub struct Multipart(pub mime::Multipart, pub Vec<Part<'a>>);
|
||||
pub struct Message(pub mime::Message, pub imf::message::Message, pub Part<'a>);
|
||||
pub struct Text(pub mime::Text, pub &'a [u8]);
|
||||
pub struct Binary(pub mime::Binary, pub &'a [u8]);
|
||||
|
||||
pub struct AnyPart<'a> {
|
||||
Mult(Multipart<'a>),
|
||||
Msg(Message<'a>),
|
||||
Txt(Text<'a>),
|
||||
Bin(Binary<'a>),
|
||||
}
|
||||
|
||||
pub struct Part<'a> {
|
||||
List(Vec<Part<'a>>),
|
||||
Single(Part<'a>),
|
||||
Leaf(&'a [u8]),
|
||||
pub enum MixedField<'a> {
|
||||
MIME(mime::fields::Content<'a>),
|
||||
IMF(rfc5322::fields::Field<'a>),
|
||||
}
|
||||
impl<'a> MixedField<'a> {
|
||||
pub fn mime(&self) -> Option<&mime::fields::Content<'a>> {
|
||||
match self {
|
||||
MIME(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn imf(&self) -> Option<&rfc5322::fields::Field<'a>> {
|
||||
match self {
|
||||
IMF(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a, MixedField> CompFieldList<'a, MixedField> {
|
||||
pub fn sections(self) -> (mime::mime::AnyMIME<'a>, imf::message::Message<'a>) {
|
||||
let k = self.known();
|
||||
let mime = k.iter().map(MixedField::mime).flatten().collect::<mime::mime::AnyMIME>();
|
||||
let imf = k.iter().map(MixedField::imf).flatten().collect::<imf::message::Message>();
|
||||
(mime, imf)
|
||||
}
|
||||
}
|
||||
pub fn mixed_field(input: &[u8]) -> IResult<&[u8], MixedField> {
|
||||
alt((
|
||||
map(mime::fields::content, MixedField::MIME),
|
||||
map(rfc5322::fields::field, MixedField::IMF),
|
||||
))(input)
|
||||
}
|
||||
|
||||
pub fn message() -> IResult<&[u8], Part> {
|
||||
}
|
||||
|
||||
pub fn multipart<'a>(m: Multipart<MIME>) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Part<'a>> {
|
||||
pub fn message<'a>(m: mime::Message<'a>) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Message<'a>> {
|
||||
move |input: &[u8]| {
|
||||
let (mut input_loop, _) = preamble(m.ctype.boundary)(input)?;
|
||||
let mut parts: Vec<Part> = vec![];
|
||||
let (input, fields) = header(mixed_field)(input)?;
|
||||
let (in_mime, imf) = fields.sections();
|
||||
|
||||
let part = to_anypart(in_mime, input);
|
||||
|
||||
Ok((&b[], Message(m, imf, part)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn multipart<'a>(m: mime::Multipart<'a>) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Multipart<'a>> {
|
||||
move |input: &[u8]| {
|
||||
let (mut input_loop, _) = part_raw(m.ctype.boundary)(input)?;
|
||||
let mut mparts: Vec<AnyPart> = vec![];
|
||||
loop {
|
||||
let input = match boundary(m.ctype.boundary)(input_loop) {
|
||||
Err(_) => return Ok((input_loop, parts)),
|
||||
Ok((inp, Delimiter::Last)) => return Ok((inp, Part::List(parts))),
|
||||
Err(_) => return Ok((input_loop, Multipart(m, mparts))),
|
||||
Ok((inp, Delimiter::Last)) => return Ok((inp, Multipart(m, mparts))),
|
||||
Ok((inp, Delimiter::Next)) => inp,
|
||||
};
|
||||
|
||||
// parse mime headers
|
||||
let (input, fields) = header_in_boundaries(ctype.boundary, content)(input)?;
|
||||
let (input, fields) = header(content)(input)?;
|
||||
let mime = fields.to_mime();
|
||||
|
||||
// parse raw part
|
||||
let (input, rpart) = part_raw(ctype.boundary.as_bytes())(input)?;
|
||||
|
||||
// parse mime body
|
||||
match mime.part_type {
|
||||
Type::Multipart(m) => multipart(m),
|
||||
Type::Message(m) => message(m),
|
||||
Type::Text(t) | Type::Binary
|
||||
}
|
||||
|
||||
// based on headers, parse part
|
||||
|
||||
let input = match part(bound)(input) {
|
||||
Err(_) => return Ok((input, parts)),
|
||||
Ok((inp, part)) => {
|
||||
parts.push(part);
|
||||
inp
|
||||
}
|
||||
};
|
||||
mparts.push(to_anypart(mime, rpart);
|
||||
|
||||
input_loop = input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn discrete() -> IResult<&[u8], Part> {
|
||||
pub fn to_anypart(m: AnyMIME<'a>, rpart: &[u8]) -> AnyPart<'a> {
|
||||
match mime {
|
||||
AnyMIME::Mult(a) => map(multipart(a), AnyPart::Mult)(rpart)
|
||||
.unwrap_or(AnyPart::Text(Text::default(), rpart)),
|
||||
AnyMIME::Msg(a) => map(message(a), AnyPart::Msg)(rpart)
|
||||
.unwrap_or(AnyPart::Text(Text::default(), rpart)),
|
||||
AnyMIME::Txt(a) => AnyPart::Txt(Text(a, rpart)),
|
||||
AnyMIME::Bin(a) => AnyPart::Bin(Binary(a, rpart)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part<'a>(bound: &'a [u8]) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
|
||||
|
||||
pub fn part_raw<'a>(bound: &'a [u8]) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
|
||||
move |input: &[u8]| {
|
||||
recognize(many0(pair(
|
||||
not(boundary(bound)),
|
||||
|
@ -74,6 +114,7 @@ pub fn part<'a>(bound: &'a [u8]) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &'a [
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn preamble<'a>(bound: &'a [u8]) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
|
||||
move |input: &[u8]| {
|
||||
recognize(many0(tuple((
|
||||
|
@ -81,7 +122,7 @@ pub fn preamble<'a>(bound: &'a [u8]) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], &
|
|||
many0(pair(not(boundary(bound)), obs_crlf)),
|
||||
))))(input)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// FIXME parse email here
|
||||
|
||||
|
@ -111,7 +152,7 @@ Field: Body
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_part() {
|
||||
fn test_part_raw() {
|
||||
assert_eq!(
|
||||
part(b"simple boundary")(b"Content-type: text/plain; charset=us-ascii
|
||||
|
||||
|
|
Loading…
Reference in a new issue