use std::iter::IntoIterator;
use vec1::Vec1;
use soft_ascii_string::SoftAsciiChar;
use internals::error::EncodingError;
use internals::encoder::{EncodableInHeader, EncodingWriter};
use ::{ HeaderTryFrom, HeaderTryInto};
use ::error::ComponentCreationError;
use super::Mailbox;
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
pub struct OptMailboxList( pub Vec<Mailbox> );
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
pub struct MailboxList( pub Vec1<Mailbox> );
impl MailboxList {
pub fn from_single( m: Mailbox ) -> Self {
MailboxList( Vec1::new( m ) )
}
}
impl IntoIterator for MailboxList {
type Item = <Vec1<Mailbox> as IntoIterator>::Item;
type IntoIter = <Vec1<Mailbox> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl EncodableInHeader for OptMailboxList {
fn encode(&self, handle: &mut EncodingWriter) -> Result<(), EncodingError> {
encode_list( self.0.iter(), handle )
}
fn boxed_clone(&self) -> Box<EncodableInHeader> {
Box::new(self.clone())
}
}
impl<T> HeaderTryFrom<Vec<T>> for MailboxList
where T: HeaderTryInto<Mailbox>
{
fn try_from(vec: Vec<T>) -> Result<Self, ComponentCreationError> {
try_from_into_iter( vec )
}
}
fn try_from_into_iter<IT>( mboxes: IT ) -> Result<MailboxList, ComponentCreationError>
where IT: IntoIterator, IT::Item: HeaderTryInto<Mailbox>
{
let mut iter = mboxes.into_iter();
let mut vec = if let Some( first) = iter.next() {
Vec1::new( first.try_into()? )
} else {
return Err(ComponentCreationError::new("MailboxList"));
};
for mbox in iter {
vec.push( mbox.try_into()? );
}
Ok( MailboxList( vec ) )
}
macro_rules! impl_header_try_from_array {
(_MBoxList 0) => ();
(_MBoxList $len:tt) => (
impl<T> HeaderTryFrom<[T; $len]> for MailboxList
where T: HeaderTryInto<Mailbox>
{
fn try_from( vec: [T; $len] ) -> Result<Self, ComponentCreationError> {
let heapified: Box<[T]> = Box::new(vec);
let vecified: Vec<_> = heapified.into();
try_from_into_iter( vecified )
}
}
);
(_OptMBoxList $len:tt) => (
impl<T> HeaderTryFrom<[T; $len]> for OptMailboxList
where T: HeaderTryInto<Mailbox>
{
fn try_from( vec: [T; $len] ) -> Result<Self, ComponentCreationError> {
let heapified: Box<[T]> = Box::new(vec);
let vecified: Vec<_> = heapified.into();
let mut out = Vec::new();
for ele in vecified.into_iter() {
out.push( ele.try_into()? );
}
Ok( OptMailboxList( out ) )
}
}
);
($($len:tt)*) => ($(
impl_header_try_from_array!{ _MBoxList $len }
impl_header_try_from_array!{ _OptMBoxList $len }
)*);
}
impl_header_try_from_array! {
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32
}
macro_rules! impl_header_try_from_tuple {
(_MBoxList []) => (
compiler_error!("mailbox list needs at last one element")
);
(_MBoxList [ $($vs:ident),* ]) => (
impl< $($vs),* > HeaderTryFrom<( $($vs,)* )> for MailboxList
where $($vs: HeaderTryInto<Mailbox>),*
{
#[allow(non_snake_case)]
fn try_from( ($($vs,)*): ($($vs,)*) ) -> Result<Self, ComponentCreationError> {
let mut out = Vec::new();
$(
let $vs = $vs.try_into()?;
out.push($vs);
)*
Ok( MailboxList(
$crate::vec1::Vec1::from_vec(out).unwrap()
) )
}
}
);
(_OptMBoxList [$($vs:ident),*]) => (
impl< $($vs),* > HeaderTryFrom<( $($vs,)* )> for OptMailboxList
where $($vs: HeaderTryInto<Mailbox>),*
{
#[allow(non_snake_case)]
fn try_from( ($($vs,)*): ($($vs,)*) ) -> Result<Self, ComponentCreationError> {
let mut out = Vec::new();
$(
let $vs = $vs.try_into()?;
out.push($vs);
)*
Ok( OptMailboxList( out ) )
}
}
);
([]) => ();
([$first_vs:ident $(, $vs:ident)*]) => (
impl_header_try_from_tuple!{ _MBoxList [$first_vs $(, $vs)* ] }
impl_header_try_from_tuple!{ _OptMBoxList [$first_vs $(, $vs)*] }
impl_header_try_from_tuple!{ [$($vs),*] }
);
}
impl_header_try_from_tuple! {
[
A0, A1, A2, A3, A4, A5, A6, A7,
A8, A9, A10, A11, A12, A13, A14, A15,
A16, A17, A18, A19, A20, A21, A22, A23,
A24, A25, A26, A27, A28, A29, A30, A31
]
}
impl<T> HeaderTryFrom<Vec<T>> for OptMailboxList
where T: HeaderTryInto<Mailbox>
{
fn try_from(vec: Vec<T>) -> Result<Self, ComponentCreationError> {
let mut out = Vec::new();
for ele in vec.into_iter() {
out.push( ele.try_into()? );
}
Ok( OptMailboxList( out ) )
}
}
impl EncodableInHeader for MailboxList {
fn encode(&self, handle: &mut EncodingWriter) -> Result<(), EncodingError> {
encode_list( self.0.iter(), handle )
}
fn boxed_clone(&self) -> Box<EncodableInHeader> {
Box::new(self.clone())
}
}
fn encode_list<'a, I>(list_iter: I, handle: &mut EncodingWriter) -> Result<(), EncodingError>
where I: Iterator<Item=&'a Mailbox>
{
sep_for!{ mailbox in list_iter;
sep {
handle.write_char( SoftAsciiChar::from_unchecked(',') )?;
handle.write_fws();
};
mailbox.encode( handle )?;
}
Ok( () )
}
deref0!{ +mut OptMailboxList => Vec<Mailbox> }
deref0!{ +mut MailboxList => Vec1<Mailbox> }
#[cfg(test)]
mod test {
use ::header_components::{ Mailbox, Email, Phrase };
use super::*;
ec_test! { empty_list, {
OptMailboxList( Vec::new() )
} => ascii => [
]}
ec_test! { single, {
MailboxList( vec1![
Mailbox {
display_name: Some( Phrase::try_from( "hy ho" )? ),
email: Email::try_from( "ran@dom" )?
},
] )
} => ascii => [
Text "hy",
MarkFWS,
Text " ho",
MarkFWS,
Text " <",
MarkFWS,
Text "ran",
MarkFWS,
Text "@",
MarkFWS,
Text "dom",
MarkFWS,
Text ">"
]}
ec_test! { multiple, {
MailboxList( vec1![
Mailbox {
display_name: Some( Phrase::try_from( "hy ho" )? ),
email: Email::try_from( "nar@mod" )?
},
Mailbox {
display_name: None,
email: Email::try_from( "ran@dom" )?
}
] )
} => ascii => [
Text "hy",
MarkFWS,
Text " ho",
MarkFWS,
Text " <",
MarkFWS,
Text "nar",
MarkFWS,
Text "@",
MarkFWS,
Text "mod",
MarkFWS,
Text ">,",
MarkFWS,
Text " <",
MarkFWS,
Text "ran",
MarkFWS,
Text "@",
MarkFWS,
Text "dom",
MarkFWS,
Text ">"
]}
}