mail_internals/bind/encoded_word/
mod.rs

1use soft_ascii_string::{ SoftAsciiStr, SoftAsciiChar };
2
3use super::{base64, quoted_printable};
4
5mod impls;
6pub use self::impls::*;
7
8#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
9pub enum EncodedWordEncoding {
10    Base64, QuotedPrintable
11}
12
13impl EncodedWordEncoding {
14
15    /// returns the acronym for the given encoding
16    /// used in a encoded word
17    pub fn acronym(&self) -> &'static SoftAsciiStr {
18        use self::EncodedWordEncoding::*;
19        match *self {
20            Base64 => SoftAsciiStr::from_unchecked("B"),
21            QuotedPrintable => SoftAsciiStr::from_unchecked("Q")
22        }
23    }
24
25    /// encodes a given utf8 string
26    ///
27    /// either `self::quoted_printable::encoded_word_encode`
28    /// or `self::base64::encoded_word_encode_utf8` is used
29    /// depending on which value `self` is.
30    ///
31    /// As both algorithm need to know about code point boundaries
32    /// only encoding utf8 is supported for now
33    ///
34    pub fn encode<R, O>(&self, input: R, out: &mut O)
35        where R: AsRef<str>, O: EncodedWordWriter
36    {
37        use self::EncodedWordEncoding::*;
38        let input: &str = input.as_ref();
39        match *self {
40            Base64 => {
41                base64::encoded_word_encode(input, out)
42            },
43            QuotedPrintable => {
44                quoted_printable::encoded_word_encode_utf8(input, out)
45            }
46        }
47    }
48}
49
50pub trait EncodedWordWriter {
51    fn write_char( &mut self, ch: SoftAsciiChar );
52    fn write_charset( &mut self );
53    fn encoding( &self ) -> EncodedWordEncoding;
54    fn write_ecw_seperator( &mut self );
55
56    /// Returns the maximal length of the paylod/encoded data
57    ///
58    /// Any number of calls to methods on in trait in any way
59    /// should never be able to change the returned value.
60    /// Only changing e.g. the charset or encoding should be
61    /// able to change what `max_paylod_len` returns.
62    fn max_payload_len( &self ) -> usize;
63
64    fn write_ecw_start( &mut self ) {
65        let qm = SoftAsciiChar::from_unchecked('?');
66        self.write_char(SoftAsciiChar::from_unchecked('='));
67        self.write_char(qm);
68        self.write_charset();
69        self.write_char(qm);
70        let acronym = self.encoding().acronym();
71        self.write_str( acronym );
72        self.write_char(qm);
73    }
74
75    fn write_ecw_end( &mut self ) {
76        self.write_char( SoftAsciiChar::from_unchecked('?') );
77        self.write_char( SoftAsciiChar::from_unchecked('=') );
78    }
79
80
81    fn start_next_encoded_word( &mut self )  {
82        self.write_ecw_end();
83        self.write_ecw_seperator();
84        self.write_ecw_start();
85    }
86
87    fn write_str( &mut self, s: &SoftAsciiStr ) {
88        for ch in s.chars() {
89            self.write_char(ch)
90        }
91    }
92}