mail_headers_ng/
header.rs

1use std::any::TypeId;
2use std::ops::{Deref, DerefMut};
3use std::fmt::{self, Debug};
4
5use internals::{
6    error::EncodingError,
7    encoder::{
8        EncodableInHeader,
9        EncodingWriter,
10    }
11};
12
13
14use ::error::ComponentCreationError;
15use ::convert::HeaderTryInto;
16use ::name::{HeaderName, HasHeaderName};
17//NOTE: this is a circular dependency between Header/HeaderMap
18// but putting up e.g. a GenericHeaderMap trait/interface is
19// not worth the work at all
20use ::map::HeaderMapValidator;
21
22/// Trait representing a mail header.
23///
24/// **This is not meant to be implemented by hand.***
25/// Use the `def_headers` macro instead.
26///
27pub trait HeaderKind: Clone + Default + 'static {
28
29    /// the component representing the header-field, e.g. `Unstructured` for `Subject`
30    type Component: EncodableInHeader + Clone;
31
32    //FIXME[rust/const fn]: make this a associated constant
33    /// a method returning the header name
34    ///
35    /// # Note:
36    /// Once `const fn` is stable this will be changed to
37    /// a associated constant.
38    fn name() -> HeaderName;
39
40    /// A function which is meant to be called with a reference
41    /// to the final header map before encoding the headers. It is
42    /// meant to be used do some of the contextual validations,
43    /// like e.g. a `From` header might return a function which
44    /// checks if the `From` header has multiple mailboxes and
45    /// if so checks if there is a `Sender` header
46    ///
47    /// Calling a contextual validator with a header map not
48    /// containing a header which it is meant to validate
49    /// should not cause an error. Only if the header is
50    /// there and the component is of the expected type
51    /// and it is invalid in the context
52    /// an error should be returned.
53    const VALIDATOR: Option<HeaderMapValidator>;
54
55    /// I true this will assure that the header is at most one time in a header map.
56    ///
57    /// This is similar to `VALIDATOR` (and can be archived through one) but in difference
58    /// to any `VALIDATOR` this is already assured when inserting a header with MAX_ONE set
59    /// to true in a header map. It exists so that the header map can do, what is most
60    /// intuitive, replacing insertion for all `MAX_ONE` headers (like in a normal map) but
61    /// use adding insertion for all other header (like in a multi map).
62    ///
63    /// Most headers have this set to true.
64    const MAX_ONE: bool;
65
66    /// Creates a `Header` instance automatically converting given body to the right type.
67    ///
68    /// # Error
69    ///
70    /// The type system assure that you can only use it on conversions
71    /// which are possible on type level, but they can still fail depending
72    /// on the actual data. For example creating a `Email`  from a string
73    /// can fail if the string is not a valid email address. This in
74    /// turn means that creating a `From` header from a array of strings
75    /// can fail if one of them is not a valid email address.
76    fn auto_body<H>(body: H) -> Result<Header<Self>, ComponentCreationError>
77        where H: HeaderTryInto<Self::Component>
78    {
79        Ok(Self::body(HeaderTryInto::try_into(body)?))
80    }
81
82    /// Creates a `Header` instance for this header kind with given body.
83    fn body(body: Self::Component) -> Header<Self> {
84        Header::new(body)
85    }
86}
87
88impl<H> HasHeaderName for H
89    where H: HeaderKind
90{
91    fn get_name(&self) -> HeaderName {
92        H::name()
93    }
94}
95
96pub trait MaxOneMarker: HeaderKind {}
97
98#[derive(Clone)]
99pub struct Header<H>
100    where H: HeaderKind
101{
102    body: H::Component
103}
104
105impl<H> Header<H>
106    where H: HeaderKind
107{
108    pub fn new(body: H::Component) -> Header<H> {
109        Header { body }
110    }
111
112    pub fn body(&self) -> &H::Component {
113        &self.body
114    }
115
116    pub fn body_mut(&mut self) -> &mut H::Component {
117        &mut self.body
118    }
119}
120
121impl<H> Deref for Header<H>
122    where H: HeaderKind
123{
124    type Target = H::Component;
125    fn deref(&self) -> &Self::Target {
126        self.body()
127    }
128}
129
130impl<H> DerefMut for Header<H>
131    where H: HeaderKind
132{
133    fn deref_mut(&mut self) -> &mut Self::Target {
134        self.body_mut()
135    }
136}
137
138impl<H> Debug for Header<H>
139    where H: HeaderKind
140{
141    fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
142        self.body.fmt(fter)
143    }
144}
145
146/// Type alias for HeaderObjTrait's trait object.
147pub type HeaderObj = dyn HeaderObjTrait;
148
149pub trait HeaderObjTrait: Sync + Send + ::std::any::Any + Debug {
150    fn name(&self) -> HeaderName;
151    fn is_max_one(&self) -> bool;
152    fn validator(&self) -> Option<HeaderMapValidator>;
153    fn encode(&self, encoder: &mut EncodingWriter) -> Result<(), EncodingError>;
154    fn boxed_clone(&self) -> Box<HeaderObj>;
155
156    #[doc(hidden)]
157    fn type_id(&self) -> TypeId {
158        TypeId::of::<Self>()
159    }
160}
161
162impl<H> HeaderObjTrait for Header<H>
163    where H: HeaderKind
164{
165    fn name(&self) -> HeaderName {
166        H::name()
167    }
168
169    fn is_max_one(&self) -> bool {
170        H::MAX_ONE
171    }
172
173    fn validator(&self) -> Option<HeaderMapValidator> {
174        H::VALIDATOR
175    }
176
177    fn encode(&self, encoder: &mut EncodingWriter) -> Result<(), EncodingError> {
178        self.body.encode(encoder)
179    }
180
181    fn boxed_clone(&self) -> Box<HeaderObj> {
182        let cloned = self.clone();
183        Box::new(cloned)
184    }
185}
186
187impl<H> HasHeaderName for Header<H>
188    where H: HeaderKind
189{
190    fn get_name(&self) -> HeaderName {
191        H::name()
192    }
193}
194
195
196impl HeaderObj {
197    pub fn is<H>(&self) -> bool
198        where H: HeaderKind
199    {
200        HeaderObjTrait::type_id(self) == TypeId::of::<Header<H>>()
201    }
202
203    pub fn downcast_ref<H>(&self) -> Option<&Header<H>>
204        where H: HeaderKind
205    {
206        if self.is::<H>() {
207            Some(unsafe { &*(self as *const _ as *const Header<H>) })
208        } else {
209            None
210        }
211    }
212
213    pub fn downcast_mut<H>(&mut self) -> Option<&mut Header<H>>
214        where H: HeaderKind
215    {
216        if self.is::<H>() {
217            Some(unsafe { &mut *(self as *mut _ as *mut Header<H>) })
218        } else {
219            None
220        }
221    }
222}
223
224impl Clone for Box<HeaderObj> {
225    fn clone(&self) -> Self {
226        self.boxed_clone()
227    }
228}
229
230impl HasHeaderName for HeaderObj {
231    fn get_name(&self) -> HeaderName {
232        self.name()
233    }
234}
235
236pub trait HeaderObjTraitBoxExt: Sized {
237    fn downcast<H>(self) -> Result<Box<Header<H>>, Self>
238        where H: HeaderKind;
239}
240
241impl HeaderObjTraitBoxExt for Box<HeaderObjTrait> {
242
243    fn downcast<H>(self) -> Result<Box<Header<H>>, Self>
244        where H: HeaderKind
245    {
246        if HeaderObjTrait::is::<H>(&*self) {
247            let ptr: *mut (HeaderObj) = Box::into_raw(self);
248            Ok(unsafe { Box::from_raw(ptr as *mut Header<H>) })
249        } else {
250            Err(self)
251        }
252    }
253}