diff --git a/Cargo.toml b/Cargo.toml index b745a98e..ae64e75d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,6 @@ xml-rs = "0.3.6" openssl = "0.9.7" base64 = "0.4.0" minidom = "0.1.0" + +[dependencies.jid] +git = "https://gitlab.com/lumi/jid-rs.git" diff --git a/src/jid.rs b/src/jid.rs deleted file mode 100644 index 2436d392..00000000 --- a/src/jid.rs +++ /dev/null @@ -1,311 +0,0 @@ -//! Provides a type for Jabber IDs. - -use std::fmt; - -use std::convert::Into; - -use std::str::FromStr; - -/// An error that signifies that a `Jid` cannot be parsed from a string. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum JidParseError { - NoDomain, -} - -/// A struct representing a Jabber ID. -/// -/// A Jabber ID is composed of 3 components, of which 2 are optional: -/// -/// - A node/name, `node`, which is the optional part before the @. -/// - A domain, `domain`, which is the mandatory part after the @ but before the /. -/// - A resource, `resource`, which is the optional part after the /. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Jid { - /// The node part of the Jabber ID, if it exists, else None. - pub node: Option, - /// The domain of the Jabber ID. - pub domain: String, - /// The resource of the Jabber ID, if it exists, else None. - pub resource: Option, -} - -impl fmt::Display for Jid { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - // TODO: may need escaping - if let Some(ref node) = self.node { - write!(fmt, "{}@", node)?; - } - write!(fmt, "{}", self.domain)?; - if let Some(ref resource) = self.resource { - write!(fmt, "/{}", resource)?; - } - Ok(()) - } -} - -enum ParserState { - Node, - Domain, - Resource -} - -impl FromStr for Jid { - type Err = JidParseError; - - fn from_str(s: &str) -> Result { - // TODO: very naive, may need to do it differently - let iter = s.chars(); - let mut buf = String::new(); - let mut state = ParserState::Node; - let mut node = None; - let mut domain = None; - let mut resource = None; - for c in iter { - match state { - ParserState::Node => { - match c { - '@' => { - state = ParserState::Domain; - node = Some(buf.clone()); // TODO: performance tweaks, do not need to copy it - buf.clear(); - }, - '/' => { - state = ParserState::Resource; - domain = Some(buf.clone()); // TODO: performance tweaks - buf.clear(); - }, - c => { - buf.push(c); - }, - } - }, - ParserState::Domain => { - match c { - '/' => { - state = ParserState::Resource; - domain = Some(buf.clone()); // TODO: performance tweaks - buf.clear(); - }, - c => { - buf.push(c); - }, - } - }, - ParserState::Resource => { - buf.push(c); - }, - } - } - if !buf.is_empty() { - match state { - ParserState::Node => { - domain = Some(buf); - }, - ParserState::Domain => { - domain = Some(buf); - }, - ParserState::Resource => { - resource = Some(buf); - }, - } - } - Ok(Jid { - node: node, - domain: domain.ok_or(JidParseError::NoDomain)?, - resource: resource, - }) - } -} - -impl Jid { - /// Constructs a Jabber ID containing all three components. - /// - /// This is of the form `node`@`domain`/`resource`. - /// - /// # Examples - /// - /// ``` - /// use xmpp::jid::Jid; - /// - /// let jid = Jid::full("node", "domain", "resource"); - /// - /// assert_eq!(jid.node, Some("node".to_owned())); - /// assert_eq!(jid.domain, "domain".to_owned()); - /// assert_eq!(jid.resource, Some("resource".to_owned())); - /// ``` - pub fn full(node: NS, domain: DS, resource: RS) -> Jid - where NS: Into - , DS: Into - , RS: Into { - Jid { - node: Some(node.into()), - domain: domain.into(), - resource: Some(resource.into()), - } - } - - /// Constructs a Jabber ID containing only the `node` and `domain` components. - /// - /// This is of the form `node`@`domain`. - /// - /// # Examples - /// - /// ``` - /// use xmpp::jid::Jid; - /// - /// let jid = Jid::bare("node", "domain"); - /// - /// assert_eq!(jid.node, Some("node".to_owned())); - /// assert_eq!(jid.domain, "domain".to_owned()); - /// assert_eq!(jid.resource, None); - /// ``` - pub fn bare(node: NS, domain: DS) -> Jid - where NS: Into - , DS: Into { - Jid { - node: Some(node.into()), - domain: domain.into(), - resource: None, - } - } - - /// Constructs a Jabber ID containing only a `domain`. - /// - /// This is of the form `domain`. - /// - /// # Examples - /// - /// ``` - /// use xmpp::jid::Jid; - /// - /// let jid = Jid::domain("domain"); - /// - /// assert_eq!(jid.node, None); - /// assert_eq!(jid.domain, "domain".to_owned()); - /// assert_eq!(jid.resource, None); - /// ``` - pub fn domain(domain: DS) -> Jid - where DS: Into { - Jid { - node: None, - domain: domain.into(), - resource: None, - } - } - - /// Constructs a Jabber ID containing the `domain` and `resource` components. - /// - /// This is of the form `domain`/`resource`. - /// - /// # Examples - /// - /// ``` - /// use xmpp::jid::Jid; - /// - /// let jid = Jid::domain_with_resource("domain", "resource"); - /// - /// assert_eq!(jid.node, None); - /// assert_eq!(jid.domain, "domain".to_owned()); - /// assert_eq!(jid.resource, Some("resource".to_owned())); - /// ``` - pub fn domain_with_resource(domain: DS, resource: RS) -> Jid - where DS: Into - , RS: Into { - Jid { - node: None, - domain: domain.into(), - resource: Some(resource.into()), - } - } - - /// Constructs a new Jabber ID from an existing one, with the node swapped out with a new one. - /// - /// # Examples - /// - /// ``` - /// use xmpp::jid::Jid; - /// - /// let jid = Jid::domain("domain"); - /// - /// assert_eq!(jid.node, None); - /// - /// let new_jid = jid.with_node("node"); - /// - /// assert_eq!(new_jid.node, Some("node".to_owned())); - /// ``` - pub fn with_node(&self, node: S) -> Jid - where S: Into { - Jid { - node: Some(node.into()), - domain: self.domain.clone(), - resource: self.resource.clone(), - } - } - - /// Constructs a new Jabber ID from an existing one, with the domain swapped out with a new one. - /// - /// # Examples - /// - /// ``` - /// use xmpp::jid::Jid; - /// - /// let jid = Jid::domain("domain"); - /// - /// assert_eq!(jid.domain, "domain"); - /// - /// let new_jid = jid.with_domain("new_domain"); - /// - /// assert_eq!(new_jid.domain, "new_domain"); - /// ``` - pub fn with_domain(&self, domain: S) -> Jid - where S: Into { - Jid { - node: self.node.clone(), - domain: domain.into(), - resource: self.resource.clone(), - } - } - - /// Constructs a new Jabber ID from an existing one, with the resource swapped out with a new one. - /// - /// # Examples - /// - /// ``` - /// use xmpp::jid::Jid; - /// - /// let jid = Jid::domain("domain"); - /// - /// assert_eq!(jid.resource, None); - /// - /// let new_jid = jid.with_resource("resource"); - /// - /// assert_eq!(new_jid.resource, Some("resource".to_owned())); - /// ``` - pub fn with_resource(&self, resource: S) -> Jid - where S: Into { - Jid { - node: self.node.clone(), - domain: self.domain.clone(), - resource: Some(resource.into()), - } - } - -} - -#[cfg(test)] -mod tests { - use super::*; - - use std::str::FromStr; - - #[test] - fn can_parse_jids() { - assert_eq!(Jid::from_str("a@b.c/d"), Ok(Jid::full("a", "b.c", "d"))); - assert_eq!(Jid::from_str("a@b.c"), Ok(Jid::bare("a", "b.c"))); - assert_eq!(Jid::from_str("b.c"), Ok(Jid::domain("b.c"))); - - assert_eq!(Jid::from_str(""), Err(JidParseError::NoDomain)); - - assert_eq!(Jid::from_str("a/b@c"), Ok(Jid::domain_with_resource("a", "b@c"))); - } -} diff --git a/src/lib.rs b/src/lib.rs index f35f0cdc..e741157f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,11 +2,11 @@ extern crate xml; extern crate openssl; extern crate minidom; extern crate base64; +pub extern crate jid; pub mod ns; pub mod transport; pub mod error; -pub mod jid; pub mod client; pub mod plugin; pub mod event;