use soft_ascii_string::SoftAsciiChar; use internals::error::EncodingError; use internals::encoder::{EncodableInHeader, EncodingWriter}; use ::{HeaderTryFrom, HeaderTryInto}; use ::error::ComponentCreationError; use super::Phrase; use super::Email; pub struct NoDisplayName; #[derive(Debug, Hash, Eq, PartialEq, Clone)] pub struct Mailbox { pub display_name: Option, pub email: Email } impl Mailbox { pub fn auto_gen_name(&mut self, default_fn: F) -> Result<(), ComponentCreationError> where F: FnOnce(&Email) -> Result, ComponentCreationError> { if self.display_name.is_none() { let default_name = default_fn(&self.email)?; self.display_name = default_name; } Ok(()) } pub fn with_default_name(mut self, default_fn: F) -> Result where F: FnOnce(&Email) -> Result, ComponentCreationError> { self.auto_gen_name(default_fn)?; Ok(self) } } impl From for Mailbox { fn from( email: Email ) -> Self { Mailbox { email, display_name: None, } } } impl From<(Option, Email)> for Mailbox { fn from( pair: (Option, Email) ) -> Self { let (display_name, email) = pair; Mailbox { display_name, email } } } impl HeaderTryFrom for Mailbox where E: HeaderTryInto { fn try_from(email: E) -> Result { Ok( Mailbox::from( email.try_into()? ) ) } } impl HeaderTryFrom<(NoDisplayName, E)> for Mailbox where E: HeaderTryInto { fn try_from( pair: (NoDisplayName, E) ) -> Result { let email = pair.1.try_into()?; Ok( Mailbox { display_name: None, email } ) } } impl HeaderTryFrom<(Option

, E)> for Mailbox where P: HeaderTryInto, E: HeaderTryInto { fn try_from(pair: (Option

, E)) -> Result { let display_name = if let Some( dn )= pair.0 { Some( dn.try_into()? ) } else { None }; let email = pair.1.try_into()?; Ok( Mailbox { display_name, email } ) } } impl HeaderTryFrom<(P, E)> for Mailbox where P: HeaderTryInto, E: HeaderTryInto { fn try_from( pair: (P, E) ) -> Result { let display_name = Some( pair.0.try_into()? ); let email = pair.1.try_into()?; Ok( Mailbox { display_name, email } ) } } impl EncodableInHeader for Mailbox { fn encode(&self, handle: &mut EncodingWriter) -> Result<(), EncodingError> { if let Some( display_name ) = self.display_name.as_ref() { display_name.encode( handle )?; handle.write_fws(); } //for now this always uses the "" form even if no display-name is given handle.write_char( SoftAsciiChar::from_unchecked('<') )?; self.email.encode( handle )?; handle.write_char( SoftAsciiChar::from_unchecked('>') )?; Ok( () ) } fn boxed_clone(&self) -> Box { Box::new(self.clone()) } } #[cfg(test)] mod test { use ::header_components::{ Email, Phrase }; use super::*; ec_test!{ email_only, { let email = Email::try_from( "affen@haus" )?; Mailbox::from(email) } => ascii => [ Text "<", MarkFWS, Text "affen", MarkFWS, Text "@", MarkFWS, Text "haus", MarkFWS, Text ">" ]} ec_test!{ with_display_text, { Mailbox { display_name: Some( Phrase::try_from( "ay ya" ).unwrap() ), email: Email::try_from( "affen@haus" ).unwrap(), } } => ascii => [ Text "ay", MarkFWS, Text " ya", MarkFWS, Text " <", MarkFWS, Text "affen", MarkFWS, Text "@", MarkFWS, Text "haus", MarkFWS, Text ">" ]} mod with_default_name { use super::*; #[test] fn does_nothing_if_display_name_is_set() { let mailbox = Mailbox { display_name: Some( Phrase::try_from( "ay ya" ).unwrap() ), email: Email::try_from( "ab@cd" ).unwrap(), }; let mailbox2 = mailbox.clone(); let mailbox = mailbox.with_default_name(|_| Ok(None)).unwrap(); assert_eq!(mailbox, mailbox2); } #[test] fn generates_a_display_name_if_needed() { let mailbox = Mailbox { display_name: None, email: Email::try_from( "ab@cd" ).unwrap(), }; let mailbox = mailbox.with_default_name(|email| { assert_eq!(email, &Email::try_from( "ab@cd" ).unwrap()); Ok(Some(Phrase::try_from( "ay ya" )?)) }).unwrap(); assert_eq!(mailbox, Mailbox { display_name: Some( Phrase::try_from( "ay ya" ).unwrap() ), email: Email::try_from( "ab@cd" ).unwrap(), }); } #[test] fn can_decide_to_not_generate_a_name() { let mailbox = Mailbox { display_name: None, email: Email::try_from( "ab@cd" ).unwrap(), }; let new_mailbox = mailbox.clone().with_default_name(|_| Ok(None)).unwrap(); assert_eq!(mailbox, new_mailbox); } #[test] fn forward_errors() { let mailbox = Mailbox { display_name: None, email: Email::try_from( "ab@cd" ).unwrap(), }; let result = mailbox.clone().with_default_name(|_| { Err(ComponentCreationError::new("DisplayName")) }); let err = assert_err!(result); assert_eq!(err.to_string(), "creating component DisplayName failed"); } } }