diff --git a/src/lib.rs b/src/lib.rs index cac2aa2..ae31627 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,7 @@ use nom::{ self, branch::alt, bytes::complete::{tag, take_until, take_until1, take_while, take_while1}, - character::complete::{multispace0, space0}, + character::complete::{digit1, multispace0, space0}, combinator::{opt, recognize}, error::{ErrorKind, ParseError}, multi::{many0, many1}, @@ -49,6 +49,35 @@ pub struct Account { pub jid: BareJid, pub password: String, pub resource: Option, + pub custom_host: Option, + pub custom_port: Option, +} + +impl Account { + pub fn new>(jid: BareJid, password: S) -> Account { + Account { + jid, + password: password.into(), + resource: None, + custom_host: None, + custom_port: None, + } + } + + pub fn with_resource>(mut self, resource: S) -> Account { + self.resource = Some(resource.into()); + self + } + + pub fn with_custom_host>(mut self, custom_host: S) -> Account { + self.custom_host = Some(custom_host.into()); + self + } + + pub fn with_custom_port(mut self, custom_port: u16) -> Account { + self.custom_port = Some(custom_port); + self + } } #[derive(Debug, Clone, PartialEq)] @@ -128,21 +157,35 @@ fn parse_account(s: Span) -> IResult { let name = name.trim(); let mut jid: Option = None; - let mut password: Option = None; - let mut resource: Option = None; + let mut password: Option<&str> = None; + let mut resource: Option<&str> = None; + let mut custom_host: Option<&str> = None; + let mut custom_port: Option = None; for line in lines { let (_, _, attr) = line; if let Some((key, val)) = attr.split_once(':') { - let key = key.trim(); let val = val.trim(); - if key == "jid" { - jid = Some(BareJid::from_str(val).unwrap()); - } else if key == "password" { - password = Some(String::from(val)); - } else if key == "resource" { - resource = Some(String::from(val)); + match key.trim() { + "jid" => jid = Some(BareJid::from_str(val).unwrap()), + "password" => password = Some(val), + "resource" => resource = Some(val), + "custom_host" => custom_host = Some(val), + "custom_port" => { + let val: Span = val.into(); + let (j, digits): (Span, Span) = digit1(val)?; + let val = digits.parse::().or(Err(nom::Err::Error( + nom::error::Error::from_error_kind(j, ErrorKind::Digit), + )))?; + custom_port = Some(val); + } + _ => (), } + } else { + return Err(nom::Err::Error(nom::error::Error::from_error_kind( + s, + ErrorKind::Tag, + ))); } } @@ -156,11 +199,11 @@ fn parse_account(s: Span) -> IResult { // Skip comments and empty newlines let (s, _) = allspaces(s)?; - let account = Account { - jid: jid.unwrap(), - password: password.unwrap(), - resource, - }; + let mut account = Account::new(jid.unwrap(), password.unwrap()); + account.resource = resource.map(String::from); + account.custom_host = custom_host.map(String::from); + account.custom_port = custom_port; + Ok((s, (String::from(name), account))) } @@ -243,11 +286,10 @@ mod tests { use pretty_assertions::assert_eq; fn get_account(name: &str) -> Account { - Account { - jid: BareJid::from_str(format!("{}@localhost", name).as_str()).unwrap(), - password: String::from("password"), - resource: None, - } + Account::new( + BareJid::from_str(format!("{}@localhost", name).as_str()).unwrap(), + "password", + ) } #[test] @@ -298,11 +340,7 @@ mod tests { let buf3 = "[Client] louise\njid: louise@localhost\n\tpassword: password\n"; let name = String::from("louise"); - let account = Account { - jid: BareJid::from_str("louise@localhost").unwrap(), - password: String::from("password"), - resource: None, - }; + let account = Account::new(BareJid::from_str("louise@localhost").unwrap(), "password"); assert_eq!( parse_account(buf1.into()), Ok(( @@ -312,11 +350,8 @@ mod tests { ); let name = String::from("louise's phone"); - let account = Account { - jid: BareJid::from_str("louise2@localhost").unwrap(), - password: String::from("password"), - resource: Some(String::from("resource1")), - }; + let account = Account::new(BareJid::from_str("louise2@localhost").unwrap(), "password") + .with_resource("resource1"); assert_eq!( parse_account(buf2.into()), Ok(( @@ -348,19 +383,12 @@ mod tests { let mut accounts: HashMap = HashMap::new(); accounts.insert( String::from("louise"), - Account { - jid: BareJid::from_str("louise@localhost").unwrap(), - password: String::from("password"), - resource: None, - }, + Account::new(BareJid::from_str("louise@localhost").unwrap(), "password"), ); accounts.insert( String::from("須賀子"), - Account { - jid: BareJid::from_str("sugako@localhost").unwrap(), - password: String::from("password"), - resource: Some(String::from("resource1")), - }, + Account::new(BareJid::from_str("sugako@localhost").unwrap(), "password") + .with_resource("resource1"), ); assert_eq!( parse_accounts(buf1.into()),