diff options
| author | 2023-07-11 21:28:42 +0100 | |
|---|---|---|
| committer | 2023-07-11 21:28:42 +0100 | |
| commit | f43911ccbae3856b35b0d3e8ec6ac6450e295da6 (patch) | |
| tree | 492b195cc06b08e546c059c16a748f369995eab1 /src/stanza | |
| parent | 143a0365d0822e6786cdac3530a725bbf450f38f (diff) | |
| download | luz-f43911ccbae3856b35b0d3e8ec6ac6450e295da6.tar.gz luz-f43911ccbae3856b35b0d3e8ec6ac6450e295da6.tar.bz2 luz-f43911ccbae3856b35b0d3e8ec6ac6450e295da6.zip | |
remove serde functions
Diffstat (limited to '')
| -rw-r--r-- | src/stanza/mod.rs | 4 | ||||
| -rw-r--r-- | src/stanza/sasl.rs | 24 | ||||
| -rw-r--r-- | src/stanza/stream.rs | 197 | 
3 files changed, 173 insertions, 52 deletions
| diff --git a/src/stanza/mod.rs b/src/stanza/mod.rs index 4eaa4c2..02ea277 100644 --- a/src/stanza/mod.rs +++ b/src/stanza/mod.rs @@ -1,2 +1,6 @@ +// use quick_xml::events::BytesDecl; +  pub mod sasl;  pub mod stream; + +// const DECLARATION: BytesDecl<'_> = BytesDecl::new("1.0", None, None); diff --git a/src/stanza/sasl.rs b/src/stanza/sasl.rs index c0e41ab..1f77ffa 100644 --- a/src/stanza/sasl.rs +++ b/src/stanza/sasl.rs @@ -1,32 +1,8 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Deserialize, PartialEq, Debug)] -pub struct Mechanisms { -    #[serde(rename = "$value")] -    pub mechanisms: Vec<Mechanism>, -} - -#[derive(Deserialize, PartialEq, Debug)] -pub struct Mechanism { -    #[serde(rename = "$text")] -    pub mechanism: String, -} - -#[derive(Serialize, Debug)] -#[serde(rename = "auth")]  pub struct Auth { -    #[serde(rename = "@xmlns")] -    pub ns: String, -    #[serde(rename = "@mechanism")]      pub mechanism: String, -    #[serde(rename = "$text")]      pub sasl_data: Option<String>,  } -#[derive(Deserialize, Debug)]  pub struct Challenge { -    #[serde(rename = "@xmlns")] -    pub ns: String, -    #[serde(rename = "$text")]      pub sasl_data: String,  } diff --git a/src/stanza/stream.rs b/src/stanza/stream.rs index 4c0addd..f0fb6a1 100644 --- a/src/stanza/stream.rs +++ b/src/stanza/stream.rs @@ -1,41 +1,182 @@ -use serde::{Deserialize, Serialize}; +use std::str; -use super::sasl::Mechanisms; +use quick_xml::{ +    events::{BytesStart, Event}, +    name::QName, +}; -#[derive(Serialize, Deserialize)] -#[serde(rename = "stream:stream")] -struct Stream { -    #[serde(rename = "@from")] -    from: Option<String>, -    #[serde(rename = "@id")] +use crate::{element::Element, JabberError, Result, JID}; + +const XMLNS_STREAM: &str = "http://etherx.jabber.org/streams"; +const VERSION: &str = "1.0"; + +enum XMLNS { +    Client, +    Server, +} + +impl From<XMLNS> for &str { +    fn from(xmlns: XMLNS) -> Self { +        match xmlns { +            XMLNS::Client => return "jabber:client", +            XMLNS::Server => return "jabber:server", +        } +    } +} + +impl TryInto<XMLNS> for &str { +    type Error = JabberError; + +    fn try_into(self) -> Result<XMLNS> { +        match self { +            "jabber:client" => Ok(XMLNS::Client), +            "jabber:server" => Ok(XMLNS::Server), +            _ => Err(JabberError::UnknownNamespace), +        } +    } +} + +pub struct Stream { +    from: Option<JID>,      id: Option<String>, -    #[serde(rename = "@to")] -    to: Option<String>, -    #[serde(rename = "@version")] -    version: Option<f32>, -    #[serde(rename = "@xml:lang")] +    to: Option<JID>, +    version: Option<String>,      lang: Option<String>, -    #[serde(rename = "@xmlns")] -    namespace: Option<String>, -    #[serde(rename = "@xmlns:stream")] -    stream_namespace: Option<String>, +    _ns: XMLNS,  } -#[derive(Deserialize, Debug)] -#[serde(rename = "stream:features")] -pub struct StreamFeatures { -    #[serde(rename = "$value")] -    pub features: Vec<StreamFeature>, +impl Stream { +    pub fn new_client(from: &JID, to: &JID, id: Option<String>, lang: Option<String>) -> Self { +        Self { +            from: Some(from.clone()), +            id, +            to: Some(to.clone()), +            version: Some(VERSION.to_owned()), +            lang, +            _ns: XMLNS::Client, +        } +    } + +    fn build(&self) -> BytesStart { +        let mut start = BytesStart::new("stream:stream"); +        if let Some(from) = &self.from { +            start.push_attribute(("from", from.to_string().as_str())); +        } +        if let Some(id) = &self.id { +            start.push_attribute(("id", id.as_str())); +        } +        if let Some(to) = &self.to { +            start.push_attribute(("to", to.to_string().as_str())); +        } +        if let Some(version) = &self.version { +            start.push_attribute(("version", version.to_string().as_str())); +        } +        if let Some(lang) = &self.lang { +            start.push_attribute(("xml:lang", lang.as_str())); +        } +        start.push_attribute(("xmlns", XMLNS::Client.into())); +        start.push_attribute(("xmlns:stream", XMLNS_STREAM)); +        start +    } +} + +impl<'e> Into<Element<'e>> for Stream { +    fn into(self) -> Element<'e> { +        Element { +            event: Event::Start(self.build().to_owned()), +            content: None, +        } +    }  } -#[derive(Deserialize, PartialEq, Debug)] +impl<'e> TryFrom<Element<'e>> for Stream { +    type Error = JabberError; + +    fn try_from(value: Element<'e>) -> Result<Stream> { +        let (mut from, mut id, mut to, mut version, mut lang, mut ns) = +            (None, None, None, None, None, XMLNS::Client); +        if let Event::Start(e) = value.event.as_ref() { +            for attribute in e.attributes() { +                let attribute = attribute?; +                match attribute.key { +                    QName(b"from") => { +                        from = Some(str::from_utf8(&attribute.value)?.to_string().try_into()?); +                    } +                    QName(b"id") => { +                        id = Some(str::from_utf8(&attribute.value)?.to_owned()); +                    } +                    QName(b"to") => { +                        to = Some(str::from_utf8(&attribute.value)?.to_string().try_into()?); +                    } +                    QName(b"version") => { +                        version = Some(str::from_utf8(&attribute.value)?.to_owned()); +                    } +                    QName(b"lang") => { +                        lang = Some(str::from_utf8(&attribute.value)?.to_owned()); +                    } +                    QName(b"xmlns") => { +                        ns = str::from_utf8(&attribute.value)?.try_into()?; +                    } +                    _ => { +                        println!("unknown attribute: {:?}", attribute) +                    } +                } +            } +            Ok(Stream { +                from, +                id, +                to, +                version, +                lang, +                _ns: ns, +            }) +        } else { +            Err(JabberError::ParseError) +        } +    } +} + +#[derive(PartialEq, Debug)]  pub enum StreamFeature { -    #[serde(rename = "starttls")]      StartTls, -    // TODO: other stream features -    #[serde(rename = "mechanisms")] -    Sasl(Mechanisms), +    Sasl(Vec<String>),      Bind, -    #[serde(other)]      Unknown,  } + +impl<'e> TryFrom<Element<'e>> for Vec<StreamFeature> { +    type Error = JabberError; + +    fn try_from(features_element: Element) -> Result<Self> { +        let mut features = Vec::new(); +        if let Some(content) = features_element.content { +            for feature_element in content { +                match feature_element.event { +                    Event::Start(e) => match e.name() { +                        QName(b"starttls") => features.push(StreamFeature::StartTls), +                        QName(b"mechanisms") => { +                            let mut mechanisms = Vec::new(); +                            if let Some(content) = feature_element.content { +                                for mechanism_element in content { +                                    if let Some(content) = mechanism_element.content { +                                        for mechanism_text in content { +                                            match mechanism_text.event { +                                                Event::Text(e) => mechanisms +                                                    .push(str::from_utf8(e.as_ref())?.to_owned()), +                                                _ => {} +                                            } +                                        } +                                    } +                                } +                            } +                            features.push(StreamFeature::Sasl(mechanisms)) +                        } +                        _ => {} +                    }, +                    _ => features.push(StreamFeature::Unknown), +                } +            } +        } +        Ok(features) +    } +} | 
