compile subset

This commit is contained in:
Quentin 2023-07-19 10:41:51 +02:00
parent a503eb1de6
commit 50b837438e
Signed by: quentin
GPG key ID: E9602264D639FF68
5 changed files with 31 additions and 25 deletions

View file

@ -103,7 +103,7 @@ Todo:
| 🔴 |2049 | ↳ Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples | | 🔴 |2049 | ↳ Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples |
| | | **Headers extensions** | | | | **Headers extensions** |
| 🔴 |2183 | ↳ Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field | | 🔴 |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 | | 🔴 |9228 | ↳ Delivered-To Email Header Field |
| | | **MIME extensions** | | | | **MIME extensions** |
| 🔴 |1847 | ↳ Security Multiparts for MIME: Multipart/Signed and Multipart/Encrypted | | 🔴 |1847 | ↳ Security Multiparts for MIME: Multipart/Signed and Multipart/Encrypted |

View file

@ -1,12 +1,10 @@
use encoding_rs::Encoding;
#[derive(Debug, PartialEq, Default)] #[derive(Debug, PartialEq, Default)]
pub struct Text<'a> { pub struct Text<'a> {
parts: Vec<&'a [u8]>, parts: Vec<&'a [u8]>,
} }
impl<'a> Text<'a> { impl<'a> Text<'a> {
pub fn push(&mut self, e: &[u8]) { pub fn push(&mut self, e: &'a [u8]) {
self.parts.push(e) self.parts.push(e)
} }

View file

@ -48,6 +48,14 @@ pub enum EncodedWord<'a> {
Quoted(QuotedWord<'a>), Quoted(QuotedWord<'a>),
Base64(Base64Word<'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)] #[derive(PartialEq,Debug)]
pub struct Base64Word<'a> { pub struct Base64Word<'a> {

View file

@ -2,12 +2,11 @@ use nom::{
branch::alt, branch::alt,
bytes::complete::take_while1, bytes::complete::take_while1,
character::complete::space0, character::complete::space0,
combinator::{into, map, opt}, combinator::{map, opt},
multi::{many0, many1}, multi::{many0, many1},
sequence::{preceded, tuple}, sequence::{preceded},
IResult, IResult,
}; };
use std::borrow::Cow;
use crate::text::{ use crate::text::{
quoted::quoted_string, quoted::quoted_string,
@ -52,7 +51,7 @@ impl<'a> Word<'a> {
match self { match self {
Word::Quoted(v) => v.to_string(), Word::Quoted(v) => v.to_string(),
Word::Encoded(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>>); pub struct Phrase<'a>(pub Vec<Word<'a>>);
impl<'a> Phrase<'a> { impl<'a> Phrase<'a> {
pub fn to_string(&self) -> String { 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 is_vchar(c) || is_obs_no_ws_ctl(c) || c == ascii::NULL
} }
enum UnstrToken<'a> { pub enum UnstrToken<'a> {
Init, Init,
Encoded(encoding::EncodedWord<'a>), Encoded(encoding::EncodedWord<'a>),
Plain(&'a [u8]), Plain(&'a [u8]),
@ -106,7 +105,7 @@ impl<'a> UnstrToken<'a> {
match self { match self {
UnstrToken::Init => "".into(), UnstrToken::Init => "".into(),
UnstrToken::Encoded(e) => e.to_string(), 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 { pub fn to_string(&self) -> String {
self.0.iter().fold( self.0.iter().fold(
(&UnstrToken::Init, String::new()), (&UnstrToken::Init, String::new()),
|(prev_token, result), current_token| { |(prev_token, mut result), current_token| {
match (prev_token, current_token) { match (prev_token, current_token) {
(UnstrToken::Init, v) => result.push_str(v.to_string().as_ref()), (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) => { (_, v) => {
result.push(' '); result.push(' ');
result.push_str(v.to_string().as_ref()) result.push_str(v.to_string().as_ref())
}, },
}; };
result (current_token, result)
} }
) ).1
} }
} }

View file

@ -1,8 +1,7 @@
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::{take_while1, tag}, bytes::complete::{take_while1, take, tag},
character::complete::anychar, combinator::{opt},
combinator::{recognize, opt},
multi::many0, multi::many0,
sequence::{pair, preceded}, sequence::{pair, preceded},
IResult, IResult,
@ -18,10 +17,12 @@ use crate::text::buffer;
/// quoted-pair = ("\" (VCHAR / WSP)) / obs-qp /// quoted-pair = ("\" (VCHAR / WSP)) / obs-qp
/// obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) /// obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR)
/// ``` /// ```
pub fn quoted_pair(input: &[u8]) -> IResult<&[u8], u8> { pub fn quoted_pair(input: &[u8]) -> IResult<&[u8], &[u8]> {
preceded(tag(&[ascii::SLASH]), anychar)(input) preceded(tag(&[ascii::SLASH]), take(1usize))(input)
} }
/// Allowed characters in quote /// Allowed characters in quote
/// ///
/// ```abnf /// ```abnf
@ -43,8 +44,8 @@ fn is_qtext(c: u8) -> bool {
/// ```abnf /// ```abnf
/// qcontent = qtext / quoted-pair /// qcontent = qtext / quoted-pair
/// ``` /// ```
fn qcontent(input: &u8) -> IResult<&[u8], &[u8]> { fn qcontent(input: &[u8]) -> IResult<&[u8], &[u8]> {
alt((take_while1(is_qtext), recognize(quoted_pair)))(input) alt((take_while1(is_qtext), quoted_pair))(input)
} }
/// Quoted string /// Quoted string
@ -63,7 +64,7 @@ pub fn quoted_string(input: &[u8]) -> IResult<&[u8], buffer::Text> {
let mut qstring = content let mut qstring = content
.iter() .iter()
.fold(buffer::Text::default(), |mut acc, (maybe_wsp, c)| { .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(&[ascii::SP]);
} }
acc.push(c); acc.push(c);
@ -71,8 +72,8 @@ pub fn quoted_string(input: &[u8]) -> IResult<&[u8], buffer::Text> {
}); });
let (input, maybe_wsp) = opt(fws)(input)?; let (input, maybe_wsp) = opt(fws)(input)?;
if let Some(wsp) = maybe_wsp { if let Some(_) = maybe_wsp {
qstring.push(wsp); qstring.push(&[ascii::SP]);
} }
let (input, _) = tag("\"")(input)?; let (input, _) = tag("\"")(input)?;