compile subset
This commit is contained in:
parent
a503eb1de6
commit
50b837438e
5 changed files with 31 additions and 25 deletions
|
@ -103,7 +103,7 @@ Todo:
|
|||
| 🔴 |2049 | ↳ Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples |
|
||||
| | | **Headers extensions** |
|
||||
| 🔴 |2183 | ↳ Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field |
|
||||
| 🟩 |6532 | ↳ Internationalized Email Headers |
|
||||
| 🔴 |6532 | ↳ Internationalized Email Headers |
|
||||
| 🔴 |9228 | ↳ Delivered-To Email Header Field |
|
||||
| | | **MIME extensions** |
|
||||
| 🔴 |1847 | ↳ Security Multiparts for MIME: Multipart/Signed and Multipart/Encrypted |
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
use encoding_rs::Encoding;
|
||||
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct Text<'a> {
|
||||
parts: Vec<&'a [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> Text<'a> {
|
||||
pub fn push(&mut self, e: &[u8]) {
|
||||
pub fn push(&mut self, e: &'a [u8]) {
|
||||
self.parts.push(e)
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,14 @@ pub enum EncodedWord<'a> {
|
|||
Quoted(QuotedWord<'a>),
|
||||
Base64(Base64Word<'a>),
|
||||
}
|
||||
impl<'a> EncodedWord<'a> {
|
||||
pub fn to_string(&self) -> String {
|
||||
match self {
|
||||
EncodedWord::Quoted(v) => v.to_string(),
|
||||
EncodedWord::Base64(v) => v.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Debug)]
|
||||
pub struct Base64Word<'a> {
|
||||
|
|
|
@ -2,12 +2,11 @@ use nom::{
|
|||
branch::alt,
|
||||
bytes::complete::take_while1,
|
||||
character::complete::space0,
|
||||
combinator::{into, map, opt},
|
||||
combinator::{map, opt},
|
||||
multi::{many0, many1},
|
||||
sequence::{preceded, tuple},
|
||||
sequence::{preceded},
|
||||
IResult,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::text::{
|
||||
quoted::quoted_string,
|
||||
|
@ -52,7 +51,7 @@ impl<'a> Word<'a> {
|
|||
match self {
|
||||
Word::Quoted(v) => v.to_string(),
|
||||
Word::Encoded(v) => v.to_string(),
|
||||
Word::Atom(v) => v.to_string(),
|
||||
Word::Atom(v) => encoding_rs::UTF_8.decode_without_bom_handling(v).0.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +72,7 @@ pub fn word(input: &[u8]) -> IResult<&[u8], Word> {
|
|||
pub struct Phrase<'a>(pub Vec<Word<'a>>);
|
||||
impl<'a> Phrase<'a> {
|
||||
pub fn to_string(&self) -> String {
|
||||
self.0.join(" ")
|
||||
self.0.iter().map(|v| v.to_string()).collect::<Vec<String>>().join(" ")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,7 +95,7 @@ fn is_unstructured(c: u8) -> bool {
|
|||
is_vchar(c) || is_obs_no_ws_ctl(c) || c == ascii::NULL
|
||||
}
|
||||
|
||||
enum UnstrToken<'a> {
|
||||
pub enum UnstrToken<'a> {
|
||||
Init,
|
||||
Encoded(encoding::EncodedWord<'a>),
|
||||
Plain(&'a [u8]),
|
||||
|
@ -106,7 +105,7 @@ impl<'a> UnstrToken<'a> {
|
|||
match self {
|
||||
UnstrToken::Init => "".into(),
|
||||
UnstrToken::Encoded(e) => e.to_string(),
|
||||
UnstrToken::Plain(e) => encoding_rs::UTF_8.decode_without_bom_handling(e).into_owned(),
|
||||
UnstrToken::Plain(e) => encoding_rs::UTF_8.decode_without_bom_handling(e).0.into_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,19 +115,19 @@ impl<'a> Unstructured<'a> {
|
|||
pub fn to_string(&self) -> String {
|
||||
self.0.iter().fold(
|
||||
(&UnstrToken::Init, String::new()),
|
||||
|(prev_token, result), current_token| {
|
||||
|(prev_token, mut result), current_token| {
|
||||
match (prev_token, current_token) {
|
||||
(UnstrToken::Init, v) => result.push_str(v.to_string().as_ref()),
|
||||
(UnstrToken::EncodedWord(_), UnstrToken::EncodedWord(v)) => result.push_str(v.to_string()).as_ref(),
|
||||
(UnstrToken::Encoded(_), UnstrToken::Encoded(v)) => result.push_str(v.to_string().as_ref()),
|
||||
(_, v) => {
|
||||
result.push(' ');
|
||||
result.push_str(v.to_string().as_ref())
|
||||
},
|
||||
};
|
||||
|
||||
result
|
||||
(current_token, result)
|
||||
}
|
||||
)
|
||||
).1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::{take_while1, tag},
|
||||
character::complete::anychar,
|
||||
combinator::{recognize, opt},
|
||||
bytes::complete::{take_while1, take, tag},
|
||||
combinator::{opt},
|
||||
multi::many0,
|
||||
sequence::{pair, preceded},
|
||||
IResult,
|
||||
|
@ -18,10 +17,12 @@ use crate::text::buffer;
|
|||
/// quoted-pair = ("\" (VCHAR / WSP)) / obs-qp
|
||||
/// obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR)
|
||||
/// ```
|
||||
pub fn quoted_pair(input: &[u8]) -> IResult<&[u8], u8> {
|
||||
preceded(tag(&[ascii::SLASH]), anychar)(input)
|
||||
pub fn quoted_pair(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
preceded(tag(&[ascii::SLASH]), take(1usize))(input)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Allowed characters in quote
|
||||
///
|
||||
/// ```abnf
|
||||
|
@ -43,8 +44,8 @@ fn is_qtext(c: u8) -> bool {
|
|||
/// ```abnf
|
||||
/// qcontent = qtext / quoted-pair
|
||||
/// ```
|
||||
fn qcontent(input: &u8) -> IResult<&[u8], &[u8]> {
|
||||
alt((take_while1(is_qtext), recognize(quoted_pair)))(input)
|
||||
fn qcontent(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
alt((take_while1(is_qtext), quoted_pair))(input)
|
||||
}
|
||||
|
||||
/// Quoted string
|
||||
|
@ -63,7 +64,7 @@ pub fn quoted_string(input: &[u8]) -> IResult<&[u8], buffer::Text> {
|
|||
let mut qstring = content
|
||||
.iter()
|
||||
.fold(buffer::Text::default(), |mut acc, (maybe_wsp, c)| {
|
||||
if let Some(wsp) = maybe_wsp {
|
||||
if let Some(_) = maybe_wsp {
|
||||
acc.push(&[ascii::SP]);
|
||||
}
|
||||
acc.push(c);
|
||||
|
@ -71,8 +72,8 @@ pub fn quoted_string(input: &[u8]) -> IResult<&[u8], buffer::Text> {
|
|||
});
|
||||
|
||||
let (input, maybe_wsp) = opt(fws)(input)?;
|
||||
if let Some(wsp) = maybe_wsp {
|
||||
qstring.push(wsp);
|
||||
if let Some(_) = maybe_wsp {
|
||||
qstring.push(&[ascii::SP]);
|
||||
}
|
||||
|
||||
let (input, _) = tag("\"")(input)?;
|
||||
|
|
Loading…
Reference in a new issue