aboutsummaryrefslogblamecommitdiffstats
path: root/stanza/src/xep_0297.rs
blob: 4dc8a26ca92a6d270b3bf2918c33fdcb31a9d2a7 (plain) (tree)




































































                                                                                      
use peanuts::{Element, FromElement, IntoElement};

use crate::{
    client::{self, iq::Iq, message::Message, presence::Presence},
    xep_0203::Delay,
};

pub const XMLNS: &str = "urn:xmpp:forward:0";

#[derive(Clone, Debug)]
pub struct Forwarded {
    delay: Option<Delay>,
    stanza: Option<Box<Stanza>>,
}

impl FromElement for Forwarded {
    fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
        element.check_name("forwarded")?;
        element.check_namespace(XMLNS)?;

        let delay = element.pop_child_opt()?;
        let stanza = element.pop_child_opt()?;
        let stanza = stanza.map(|stanza| Box::new(stanza));

        Ok(Self { delay, stanza })
    }
}

impl IntoElement for Forwarded {
    fn builder(&self) -> peanuts::ElementBuilder {
        Element::builder("forwarded", Some(XMLNS))
            .push_child_opt(self.delay.clone())
            .push_child_opt(self.stanza.clone().map(|stanza| *stanza))
    }
}

#[derive(Clone, Debug)]
pub enum Stanza {
    Message(Message),
    Presence(Presence),
    Iq(Iq),
    // TODO: raw elements are received with reads.
    // Raw(Element),
}

impl FromElement for Stanza {
    fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
        match element.identify() {
            (Some(client::XMLNS), "message") => {
                Ok(Stanza::Message(Message::from_element(element)?))
            }
            (Some(client::XMLNS), "presence") => {
                Ok(Stanza::Presence(Presence::from_element(element)?))
            }
            (Some(client::XMLNS), "iq") => Ok(Stanza::Iq(Iq::from_element(element)?)),
            _ => Err(peanuts::DeserializeError::UnexpectedElement(element)),
        }
    }
}

impl IntoElement for Stanza {
    fn builder(&self) -> peanuts::ElementBuilder {
        match self {
            Stanza::Message(message) => message.builder(),
            Stanza::Presence(presence) => presence.builder(),
            Stanza::Iq(iq) => iq.builder(),
        }
    }
}