mail_internals/encoder/
encodable.rs

1use std::any::{Any, TypeId};
2use std::fmt::{self, Debug};
3use std::result::{ Result as StdResult };
4use std::sync::Arc;
5
6use ::error::EncodingError;
7use super::{EncodingWriter};
8
9// can not be moved to `super::traits` as it depends on the
10// EncodingWriter defined here
11/// Trait Implemented by "components" used in header field bodies
12///
13/// This trait can be turned into a trait object allowing runtime
14/// genericallity over the "components" if needed.
15pub trait EncodableInHeader: Send + Sync + Any + Debug {
16    fn encode(&self, encoder:  &mut EncodingWriter) -> Result<(), EncodingError>;
17
18    fn boxed_clone(&self) -> Box<EncodableInHeader>;
19
20    #[doc(hidden)]
21    fn type_id(&self) -> TypeId {
22        TypeId::of::<Self>()
23    }
24}
25
26//TODO we now could use MOPA or similar crates
27impl EncodableInHeader {
28
29    #[inline(always)]
30    pub fn is<T: EncodableInHeader>(&self) -> bool {
31        EncodableInHeader::type_id(self) == TypeId::of::<T>()
32    }
33
34
35    #[inline]
36    pub fn downcast_ref<T: EncodableInHeader>(&self) -> Option<&T> {
37        if self.is::<T>() {
38            Some( unsafe { &*( self as *const EncodableInHeader as *const T) } )
39        } else {
40            None
41        }
42    }
43
44    #[inline]
45    pub fn downcast_mut<T: EncodableInHeader>(&mut self) -> Option<&mut T> {
46        if self.is::<T>() {
47            Some( unsafe { &mut *( self as *mut EncodableInHeader as *mut T) } )
48        } else {
49            None
50        }
51    }
52}
53
54impl Clone for Box<EncodableInHeader> {
55
56    fn clone(&self) -> Self {
57        self.boxed_clone()
58    }
59}
60
61
62pub trait EncodableInHeaderBoxExt: Sized {
63    fn downcast<T: EncodableInHeader>(self) -> StdResult<Box<T>, Self>;
64}
65
66impl EncodableInHeaderBoxExt for Box<EncodableInHeader> {
67
68    fn downcast<T: EncodableInHeader>(self) -> StdResult<Box<T>, Self> {
69        if EncodableInHeader::is::<T>(&*self) {
70            let ptr: *mut EncodableInHeader = Box::into_raw(self);
71            Ok( unsafe { Box::from_raw(ptr as *mut T) } )
72        } else {
73            Err( self )
74        }
75    }
76}
77
78impl EncodableInHeaderBoxExt for Box<EncodableInHeader+Send> {
79
80    fn downcast<T: EncodableInHeader>(self) -> StdResult<Box<T>, Self> {
81        if EncodableInHeader::is::<T>(&*self) {
82            let ptr: *mut EncodableInHeader = Box::into_raw(self);
83            Ok( unsafe { Box::from_raw(ptr as *mut T) } )
84        } else {
85            Err( self )
86        }
87    }
88}
89
90/// Generate a think implementing `EncodableInHeader` from an function.
91///
92/// (Mainly used in the inside of tests.)
93#[macro_export]
94macro_rules! enc_func {
95    (|$enc:ident : &mut EncodingWriter| $block:block) => ({
96        use $crate::error::EncodingError;
97        fn _anonym($enc: &mut EncodingWriter) -> Result<(), EncodingError> {
98            $block
99        }
100        let fn_pointer = _anonym as fn(&mut EncodingWriter) -> Result<(), EncodingError>;
101        $crate::encoder::EncodeFn::new(fn_pointer)
102    });
103}
104
105type _EncodeFn = for<'a, 'b> fn(&'a mut EncodingWriter<'b>) -> Result<(), EncodingError>;
106
107/// A wrapper for an function making it implement `EncodableInHeader`.
108#[derive(Clone, Copy)]
109pub struct EncodeFn(_EncodeFn);
110
111impl EncodeFn {
112    pub fn new(func: _EncodeFn) -> Self {
113        EncodeFn(func)
114    }
115}
116
117impl EncodableInHeader for EncodeFn {
118    fn encode(&self, encoder:  &mut EncodingWriter) -> Result<(), EncodingError> {
119        (self.0)(encoder)
120    }
121
122    fn boxed_clone(&self) -> Box<EncodableInHeader> {
123        Box::new(*self)
124    }
125}
126
127impl Debug for EncodeFn {
128    fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
129        write!(fter, "EncodeFn(..)")
130    }
131}
132
133/// Generate a think implementing `EncodableInHeader` from an closure.
134///
135/// (Mainly used in the inside of tests.)
136#[macro_export]
137macro_rules! enc_closure {
138    ($($t:tt)*) => ({
139        $crate::encoder::EncodeClosure::new($($t)*)
140    });
141}
142
143/// A wrapper for an closure making it implement `EncodableInHeader`.
144pub struct EncodeClosure<FN: 'static>(Arc<FN>)
145    where FN: Send + Sync +
146        for<'a, 'b> Fn(&'a mut EncodingWriter<'b>) -> Result<(), EncodingError>;
147
148impl<FN: 'static> EncodeClosure<FN>
149    where FN: Send + Sync +
150        for<'a, 'b> Fn(&'a mut EncodingWriter<'b>) -> Result<(), EncodingError>
151{
152    pub fn new(closure: FN) -> Self {
153        EncodeClosure(Arc::new(closure))
154    }
155}
156
157impl<FN: 'static> EncodableInHeader for EncodeClosure<FN>
158    where FN: Send + Sync +
159        for<'a, 'b> Fn(&'a mut EncodingWriter<'b>) -> Result<(), EncodingError>
160{
161    fn encode(&self, encoder:  &mut EncodingWriter) -> Result<(), EncodingError> {
162        (self.0)(encoder)
163    }
164
165    fn boxed_clone(&self) -> Box<EncodableInHeader> {
166        Box::new(self.clone())
167    }
168}
169
170impl<FN: 'static> Clone for EncodeClosure<FN>
171    where FN: Send + Sync +
172        for<'a, 'b> Fn(&'a mut EncodingWriter<'b>) -> Result<(), EncodingError>
173{
174    fn clone(&self) -> Self {
175        EncodeClosure(self.0.clone())
176    }
177}
178
179
180impl<FN: 'static> Debug for EncodeClosure<FN>
181    where FN: Send + Sync +
182        for<'a, 'b> Fn(&'a mut EncodingWriter<'b>) -> Result<(), EncodingError>
183{
184    fn fmt(&self, fter: &mut fmt::Formatter) -> fmt::Result {
185        write!(fter, "EncodeClosure(..)")
186    }
187}