use futures::{sink::SinkExt, task::Poll, Sink, Stream};
use std::pin::Pin;
use std::str::FromStr;
use std::task::Context;
use xmpp_parsers::{ns, Element, Jid};
use self::connect::component_login;
use super::xmpp_codec::Packet;
use super::Error;
use crate::connect::ServerConnector;
use crate::xmpp_stream::add_stanza_id;
use crate::xmpp_stream::XMPPStream;
mod auth;
pub(crate) mod connect;
pub struct Component<C: ServerConnector> {
pub jid: Jid,
stream: XMPPStream<C::Stream>,
}
impl<C: ServerConnector> Component<C> {
pub async fn new_with_connector(
jid: &str,
password: &str,
connector: C,
) -> Result<Self, Error> {
let jid = Jid::from_str(jid)?;
let password = password.to_owned();
let stream = component_login(connector, jid.clone(), password).await?;
Ok(Component { jid, stream })
}
pub async fn send_stanza(&mut self, stanza: Element) -> Result<(), Error> {
self.send(add_stanza_id(stanza, ns::COMPONENT_ACCEPT)).await
}
pub async fn send_end(&mut self) -> Result<(), Error> {
self.close().await
}
}
impl<C: ServerConnector> Stream for Component<C> {
type Item = Element;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
loop {
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(Ok(Packet::Stanza(stanza)))) => return Poll::Ready(Some(stanza)),
Poll::Ready(Some(Ok(Packet::Text(_)))) => {
}
Poll::Ready(Some(Ok(_))) =>
{
return Poll::Ready(None)
}
Poll::Ready(Some(Err(_))) => return Poll::Ready(None),
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => return Poll::Pending,
}
}
}
}
impl<C: ServerConnector> Sink<Element> for Component<C> {
type Error = Error;
fn start_send(mut self: Pin<&mut Self>, item: Element) -> Result<(), Self::Error> {
Pin::new(&mut self.stream)
.start_send(Packet::Stanza(item))
.map_err(|e| e.into())
}
fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Pin::new(&mut self.stream)
.poll_ready(cx)
.map_err(|e| e.into())
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Pin::new(&mut self.stream)
.poll_flush(cx)
.map_err(|e| e.into())
}
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Pin::new(&mut self.stream)
.poll_close(cx)
.map_err(|e| e.into())
}
}