mail_internals/bind/
quoted_string.rs

1use quoted_string::spec::{
2    GeneralQSSpec,
3    PartialCodePoint,
4    WithoutQuotingValidator
5};
6
7use media_type_impl_utils::quoted_string;
8use ::MailType;
9
10/// A Quoted String specification in context of Mail ([rfc5322](https://tools.ietf.org/html/rfc5322#section-2.2.3))
11///
12/// This implementation of MailQsSpec _does not_ include support for the obsolete parts of the grammar
13/// as it's meant for generation/encoding and no obsolete parts should be generated at all (Through
14/// a parser would have to be able to parse them for compatibility reasons).
15///
16#[derive(Copy, Clone, Debug, Default)]
17pub struct MailQsSpec;
18
19impl GeneralQSSpec for MailQsSpec {
20    type Quoting = quoted_string::NormalQuoting;
21    type Parsing = quoted_string::MimeParsing;
22}
23
24
25/// A Quoted String specification in context of Mail ([rfc5322](https://tools.ietf.org/html/rfc5322#section-2.2.3))
26///
27/// This implementation of MailQsSpec _does not_ include support for the obsolete parts of the grammar
28/// as it's meant for generation/encoding and no obsolete parts should be generated at all (Through
29/// a parser would have to be able to parse them for compatibility reasons).
30#[derive(Copy, Clone, Debug, Default)]
31pub struct InternationalizedMailQsSpec;
32
33impl GeneralQSSpec for InternationalizedMailQsSpec {
34    type Quoting = quoted_string::NormalUtf8Quoting;
35    type Parsing = quoted_string::MimeParsingUtf8;
36}
37
38pub use self::quoted_string::MimeTokenValidator as UnquotedTokenValidator;
39
40
41#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
42pub struct UnquotedATextValidator {
43    mail_type: MailType
44}
45
46impl UnquotedATextValidator {
47    pub fn new(mail_type: MailType) -> Self {
48        UnquotedATextValidator { mail_type }
49    }
50}
51
52impl WithoutQuotingValidator for UnquotedATextValidator {
53    fn next(&mut self, pcp: PartialCodePoint) -> bool {
54       is_atext(pcp, self.mail_type)
55    }
56}
57
58
59#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
60pub struct UnquotedDotAtomTextValidator {
61    mail_type: MailType,
62    allow_dot: bool
63}
64
65impl UnquotedDotAtomTextValidator {
66    pub fn new(mail_type: MailType) -> Self {
67        UnquotedDotAtomTextValidator { mail_type, allow_dot: false }
68    }
69}
70
71impl WithoutQuotingValidator for UnquotedDotAtomTextValidator {
72    fn next(&mut self, pcp: PartialCodePoint) -> bool {
73        if is_atext(pcp, self.mail_type) {
74            self.allow_dot = true;
75            true
76        } else if self.allow_dot && pcp.as_u8() == b'.' {
77            self.allow_dot = false;
78            true
79        } else {
80            false
81        }
82    }
83
84    fn end(&self) -> bool {
85        // it can't end in a dot so it's the same as allow_dot
86        // (as empty or starting with a dot is also not allowed)
87        self.allow_dot
88    }
89}
90
91
92//TODO replace with lookup table (which could be placed in `::grammar`)!
93fn is_atext(pcp: PartialCodePoint, mail_type: MailType) -> bool {
94    use grammar::is_special;
95    let iu8 = pcp.as_u8();
96    if iu8 > 0x7f {
97        mail_type == MailType::Internationalized
98    } else {
99        b'!' <= iu8 && iu8 <= b'~' && !is_special(iu8 as char)
100    }
101}