diff --git a/src/projections/xmpp/mod.rs b/src/projections/xmpp/mod.rs index c34358f..611a038 100644 --- a/src/projections/xmpp/mod.rs +++ b/src/projections/xmpp/mod.rs @@ -293,9 +293,9 @@ async fn socket_final( to: None, r#type: xmpp::client::IqType::Result, body: BindResponse(Jid { - name: Name("darova".to_string()), + name: Some(Name("darova".to_string())), server: Server("localhost".to_string()), - resource: Resource("kek".to_string()), + resource: Some(Resource("kek".to_string())), }), }; req.serialize(&mut events); diff --git a/src/protos/xmpp/bind.rs b/src/protos/xmpp/bind.rs index 0b5b1e1..ef70553 100644 --- a/src/protos/xmpp/bind.rs +++ b/src/protos/xmpp/bind.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use nom::AsBytes; use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; use quick_xml::name::{Namespace, ResolveResult}; @@ -20,30 +22,39 @@ pub struct Resource(pub String); #[derive(PartialEq, Eq, Debug)] pub struct Jid { - pub name: Name, + pub name: Option, pub server: Server, - pub resource: Resource, + pub resource: Option, +} + +impl Display for Jid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(name) = &self.name { + write!(f, "{}@", &name.0)?; + } + write!(f, "{}", &self.server.0)?; + if let Some(resource) = &self.resource { + write!(f, "/{}", &resource.0)?; + } + Ok(()) + } } impl Jid { - pub fn to_string(&self) -> String { - format!("{}@{}/{}", self.name.0, self.server.0, self.resource.0) - } - pub fn from_string(i: &str) -> Result { // TODO make regex static use regex::Regex; - let re = Regex::new(r"^([a-zA-Z]+)@([a-zA-Z.]+)/([a-zA-Z\-]+)$").unwrap(); + let re = Regex::new(r"^(([a-zA-Z]+)@)?([a-zA-Z.]+)(/([a-zA-Z\-]+))?$").unwrap(); let m = re .captures(i) .ok_or(ffail!("Incorrectly format jid: {i}"))?; - let name = m.get(1).unwrap(); - let name = Name(name.as_str().to_string()); - let server = m.get(2).unwrap(); + let name = m.get(2).map(|name| Name(name.as_str().to_string())); + let server = m.get(3).unwrap(); let server = Server(server.as_str().to_string()); - let resource = m.get(3).unwrap(); - let resource = Resource(resource.as_str().to_string()); + let resource = m + .get(5) + .map(|resource| Resource(resource.as_str().to_string())); Ok(Jid { name, @@ -199,4 +210,52 @@ mod tests { .unwrap(); assert_eq!(result, BindRequest(Resource("mobile".to_string())),) } + + #[test] + fn jid_parse_full() { + let input = "chelik@server.example/kek"; + let expected = Jid { + name: Some(Name("chelik".into())), + server: Server("server.example".into()), + resource: Some(Resource("kek".into())), + }; + let res = Jid::from_string(input).unwrap(); + assert_eq!(res, expected); + } + + #[test] + fn jid_parse_user() { + let input = "chelik@server.example"; + let expected = Jid { + name: Some(Name("chelik".into())), + server: Server("server.example".into()), + resource: None, + }; + let res = Jid::from_string(input).unwrap(); + assert_eq!(res, expected); + } + + #[test] + fn jid_parse_server() { + let input = "server.example"; + let expected = Jid { + name: None, + server: Server("server.example".into()), + resource: None, + }; + let res = Jid::from_string(input).unwrap(); + assert_eq!(res, expected); + } + + #[test] + fn jid_parse_server_resource() { + let input = "server.example/kek"; + let expected = Jid { + name: None, + server: Server("server.example".into()), + resource: Some(Resource("kek".into())), + }; + let res = Jid::from_string(input).unwrap(); + assert_eq!(res, expected); + } }