use soft_ascii_string::SoftAsciiChar; use vec1::{Vec1, Size0Error}; use internals::error::EncodingError; use internals::encoder::{EncodingWriter, EncodableInHeader}; use ::{HeaderTryFrom, HeaderTryInto}; use ::error::ComponentCreationError; use super::Phrase; #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub struct PhraseList(pub Vec1); impl IntoIterator for PhraseList { type Item = as IntoIterator>::Item; type IntoIter = as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } impl EncodableInHeader for PhraseList { fn encode(&self, handle: &mut EncodingWriter) -> Result<(), EncodingError> { sep_for!{ word in self.0.iter(); sep { //TODO handle this better by collapsing FWS // <= isn't that allready fixed by FWS+ has content on line in EncodingBuffer //Note that we do not want to write FWS as the following word might contains // a left_padding with a MarkFWS, NowChar, Text " " but a space if fine handle.write_char( SoftAsciiChar::from_unchecked(',') )?; handle.write_char( SoftAsciiChar::from_unchecked(' ') )?; }; word.encode( handle )?; } Ok( () ) } fn boxed_clone(&self) -> Box { Box::new(self.clone()) } } impl HeaderTryFrom for PhraseList where T: HeaderTryInto { fn try_from( phrase: T ) -> Result { let phrase = phrase.try_into()?; Ok( PhraseList( Vec1::new( phrase ) ) ) } } impl HeaderTryFrom> for PhraseList where T: HeaderTryInto { fn try_from(vec: Vec) -> Result { try_from_into_iter( vec ) } } fn try_from_into_iter( phrases: IT ) -> Result where IT: IntoIterator, IT::Item: HeaderTryInto { let mut iter = phrases.into_iter(); let mut vec = if let Some( first) = iter.next() { Vec1::new( first.try_into()? ) } else { return Err( ComponentCreationError ::from_parent(Size0Error, "PhraseList") ); }; for phrase in iter { vec.push( phrase.try_into()? ); } Ok( PhraseList( vec ) ) } //FIXME: dedup code duplication with: // MailboxList, PhraseList(this think here) and ?? possible future types?? macro_rules! impl_header_try_from_array { (_MBoxList 0) => (); (_MBoxList $len:tt) => ( impl HeaderTryFrom<[T; $len]> for PhraseList where T: HeaderTryInto { fn try_from( vec: [T; $len] ) -> Result { //due to only supporting arrays halfheartedly for now let heapified: Box<[T]> = Box::new(vec); let vecified: Vec<_> = heapified.into(); try_from_into_iter( vecified ) } } ); ($($len:tt)*) => ($( impl_header_try_from_array!{ _MBoxList $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 } #[cfg(test)] mod test { use super::*; ec_test!{ some_phrases, { PhraseList( vec1![ Phrase::try_from( "hy there" )?, Phrase::try_from( "magic man" )? ]) } => ascii => [ Text "hy", MarkFWS, //TODO really no FWS by the seperator?? // (currently it's this way as word can start with a FWS making it a double FWS) Text " there, magic", MarkFWS, Text " man" ]} ec_test!{ some_simple_phrases_try_from, { PhraseList::try_from( "hy there" )? } => ascii => [ Text "hy", MarkFWS, Text " there" ]} ec_test!{ some_phrases_try_from, { PhraseList::try_from( [ "hy there", "magic man" ] )? } => ascii => [ Text "hy", MarkFWS, Text " there, magic", MarkFWS, Text " man" ]} }