diff options
Diffstat (limited to 'internals/src/bind/quoted_string.rs')
-rw-r--r-- | internals/src/bind/quoted_string.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/internals/src/bind/quoted_string.rs b/internals/src/bind/quoted_string.rs new file mode 100644 index 0000000..2a5c3ab --- /dev/null +++ b/internals/src/bind/quoted_string.rs @@ -0,0 +1,101 @@ +use quoted_string::spec::{ + GeneralQSSpec, + PartialCodePoint, + WithoutQuotingValidator +}; + +use media_type_impl_utils::quoted_string; +use ::MailType; + +/// A Quoted String specification in context of Mail ([rfc5322](https://tools.ietf.org/html/rfc5322#section-2.2.3)) +/// +/// This implementation of MailQsSpec _does not_ include support for the obsolete parts of the grammar +/// as it's meant for generation/encoding and no obsolete parts should be generated at all (Through +/// a parser would have to be able to parse them for compatibility reasons). +/// +#[derive(Copy, Clone, Debug, Default)] +pub struct MailQsSpec; + +impl GeneralQSSpec for MailQsSpec { + type Quoting = quoted_string::NormalQuoting; + type Parsing = quoted_string::MimeParsing; +} + + +/// A Quoted String specification in context of Mail ([rfc5322](https://tools.ietf.org/html/rfc5322#section-2.2.3)) +/// +/// This implementation of MailQsSpec _does not_ include support for the obsolete parts of the grammar +/// as it's meant for generation/encoding and no obsolete parts should be generated at all (Through +/// a parser would have to be able to parse them for compatibility reasons). +#[derive(Copy, Clone, Debug, Default)] +pub struct InternationalizedMailQsSpec; + +impl GeneralQSSpec for InternationalizedMailQsSpec { + type Quoting = quoted_string::NormalUtf8Quoting; + type Parsing = quoted_string::MimeParsingUtf8; +} + +pub use self::quoted_string::MimeTokenValidator as UnquotedTokenValidator; + + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct UnquotedATextValidator { + mail_type: MailType +} + +impl UnquotedATextValidator { + pub fn new(mail_type: MailType) -> Self { + UnquotedATextValidator { mail_type } + } +} + +impl WithoutQuotingValidator for UnquotedATextValidator { + fn next(&mut self, pcp: PartialCodePoint) -> bool { + is_atext(pcp, self.mail_type) + } +} + + +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub struct UnquotedDotAtomTextValidator { + mail_type: MailType, + allow_dot: bool +} + +impl UnquotedDotAtomTextValidator { + pub fn new(mail_type: MailType) -> Self { + UnquotedDotAtomTextValidator { mail_type, allow_dot: false } + } +} + +impl WithoutQuotingValidator for UnquotedDotAtomTextValidator { + fn next(&mut self, pcp: PartialCodePoint) -> bool { + if is_atext(pcp, self.mail_type) { + self.allow_dot = true; + true + } else if self.allow_dot && pcp.as_u8() == b'.' { + self.allow_dot = false; + true + } else { + false + } + } + + fn end(&self) -> bool { + // it can't end in a dot so it's the same as allow_dot + // (as empty or starting with a dot is also not allowed) + self.allow_dot + } +} + + +//TODO replace with lookup table (which could be placed in `::grammar`)! +fn is_atext(pcp: PartialCodePoint, mail_type: MailType) -> bool { + use grammar::is_special; + let iu8 = pcp.as_u8(); + if iu8 > 0x7f { + mail_type == MailType::Internationalized + } else { + b'!' <= iu8 && iu8 <= b'~' && !is_special(iu8 as char) + } +} |