feat(xmpp): improve jid model

This commit is contained in:
Nikita Vilunov 2023-03-29 01:12:12 +02:00
parent a2a0a8914d
commit fbb7349585
2 changed files with 73 additions and 14 deletions

View File

@ -293,9 +293,9 @@ async fn socket_final(
to: None, to: None,
r#type: xmpp::client::IqType::Result, r#type: xmpp::client::IqType::Result,
body: BindResponse(Jid { body: BindResponse(Jid {
name: Name("darova".to_string()), name: Some(Name("darova".to_string())),
server: Server("localhost".to_string()), server: Server("localhost".to_string()),
resource: Resource("kek".to_string()), resource: Some(Resource("kek".to_string())),
}), }),
}; };
req.serialize(&mut events); req.serialize(&mut events);

View File

@ -1,3 +1,5 @@
use std::fmt::Display;
use nom::AsBytes; use nom::AsBytes;
use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event}; use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
use quick_xml::name::{Namespace, ResolveResult}; use quick_xml::name::{Namespace, ResolveResult};
@ -20,30 +22,39 @@ pub struct Resource(pub String);
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
pub struct Jid { pub struct Jid {
pub name: Name, pub name: Option<Name>,
pub server: Server, pub server: Server,
pub resource: Resource, pub resource: Option<Resource>,
}
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 { 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<Jid> { pub fn from_string(i: &str) -> Result<Jid> {
// TODO make regex static // TODO make regex static
use regex::Regex; 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 let m = re
.captures(i) .captures(i)
.ok_or(ffail!("Incorrectly format jid: {i}"))?; .ok_or(ffail!("Incorrectly format jid: {i}"))?;
let name = m.get(1).unwrap(); let name = m.get(2).map(|name| Name(name.as_str().to_string()));
let name = Name(name.as_str().to_string()); let server = m.get(3).unwrap();
let server = m.get(2).unwrap();
let server = Server(server.as_str().to_string()); let server = Server(server.as_str().to_string());
let resource = m.get(3).unwrap(); let resource = m
let resource = Resource(resource.as_str().to_string()); .get(5)
.map(|resource| Resource(resource.as_str().to_string()));
Ok(Jid { Ok(Jid {
name, name,
@ -199,4 +210,52 @@ mod tests {
.unwrap(); .unwrap();
assert_eq!(result, BindRequest(Resource("mobile".to_string())),) 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);
}
} }