xmlstream: remove T: AsXml bound from XmlStream type
While the FromXml bound is necessary for the key implementation of the XmlStream (the `impl Stream`), the AsXml bound is not as intrinsic: the Sink implementation can take any AsXml implementation on each separate send invocation. By removing this bound, we can add extra logic *only* to the parsing, without having to worry about effects on the sending side. Concretely, we'll be able to create a wrapper type for XmppStreamElement which allows us to capture errors during parsing, without having to worry about what happens during serialisation.
This commit is contained in:
parent
199218f263
commit
bda08407b0
4 changed files with 15 additions and 14 deletions
|
|
@ -25,6 +25,7 @@ Version NEXT:
|
||||||
- Update hickory-dns to 0.26 (!671)
|
- Update hickory-dns to 0.26 (!671)
|
||||||
- Drive the XMPP client stream in the background (!631)
|
- Drive the XMPP client stream in the background (!631)
|
||||||
- Add option to split XMPP client into read and write half (!631)
|
- Add option to split XMPP client into read and write half (!631)
|
||||||
|
- Remove T: AsXml bound from XmlStream (!675)
|
||||||
|
|
||||||
Version 5.0.0:
|
Version 5.0.0:
|
||||||
2025-10-28 pep <pep@bouah.net>
|
2025-10-28 pep <pep@bouah.net>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ use xmpp_parsers::{
|
||||||
stream_features::StreamFeatures,
|
stream_features::StreamFeatures,
|
||||||
};
|
};
|
||||||
|
|
||||||
use xso::{AsXml, FromXml};
|
use xso::FromXml;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
common::{RawXmlStream, ReadXso, ReadXsoError, StreamHeader},
|
common::{RawXmlStream, ReadXso, ReadXsoError, StreamHeader},
|
||||||
|
|
@ -127,7 +127,7 @@ impl<Io: AsyncBufRead + AsyncWrite + Unpin> PendingFeaturesRecv<Io> {
|
||||||
/// If the peer sends any payload which is neither stream features nor
|
/// If the peer sends any payload which is neither stream features nor
|
||||||
/// a stream error, an [`io::Error`][`std::io::Error`] with
|
/// a stream error, an [`io::Error`][`std::io::Error`] with
|
||||||
/// [`InvalidData`][`io::ErrorKind::InvalidData`] kind is returned.
|
/// [`InvalidData`][`io::ErrorKind::InvalidData`] kind is returned.
|
||||||
pub async fn recv_features<T: FromXml + AsXml>(
|
pub async fn recv_features<T: FromXml>(
|
||||||
self,
|
self,
|
||||||
) -> Result<(StreamFeatures, XmlStream<Io, T>), RecvFeaturesError> {
|
) -> Result<(StreamFeatures, XmlStream<Io, T>), RecvFeaturesError> {
|
||||||
let Self {
|
let Self {
|
||||||
|
|
@ -170,7 +170,7 @@ impl<Io: AsyncBufRead + AsyncWrite + Unpin> PendingFeaturesRecv<Io> {
|
||||||
/// down the road (because the feature stream element cannot be handled).
|
/// down the road (because the feature stream element cannot be handled).
|
||||||
/// The only place where this is useful is in
|
/// The only place where this is useful is in
|
||||||
/// [XEP-0114](https://xmpp.org/extensions/xep-0114.html) connections.
|
/// [XEP-0114](https://xmpp.org/extensions/xep-0114.html) connections.
|
||||||
pub fn skip_features<T: FromXml + AsXml>(self) -> XmlStream<Io, T> {
|
pub fn skip_features<T: FromXml>(self) -> XmlStream<Io, T> {
|
||||||
XmlStream::wrap(self.stream)
|
XmlStream::wrap(self.stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -259,7 +259,7 @@ impl<Io, T: FromXml> XmlStream<Io, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Io: AsyncBufRead, T: FromXml + AsXml> XmlStream<Io, T> {
|
impl<Io: AsyncBufRead, T: FromXml> XmlStream<Io, T> {
|
||||||
fn wrap(inner: RawXmlStream<Io>) -> Self {
|
fn wrap(inner: RawXmlStream<Io>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner,
|
inner,
|
||||||
|
|
@ -281,7 +281,7 @@ impl<Io: AsyncBufRead, T: FromXml + AsXml> XmlStream<Io, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Io: AsyncBufRead + AsyncWrite + Unpin, T: FromXml + AsXml + fmt::Debug> XmlStream<Io, T> {
|
impl<Io: AsyncBufRead + AsyncWrite + Unpin, T: FromXml + fmt::Debug> XmlStream<Io, T> {
|
||||||
/// Initiate a stream reset
|
/// Initiate a stream reset
|
||||||
///
|
///
|
||||||
/// To actually send the stream header, call
|
/// To actually send the stream header, call
|
||||||
|
|
@ -329,7 +329,7 @@ impl<Io: AsyncBufRead + AsyncWrite + Unpin, T: FromXml + AsXml + fmt::Debug> Xml
|
||||||
///
|
///
|
||||||
/// In addition, attempting to reset a stream which has been closed by
|
/// In addition, attempting to reset a stream which has been closed by
|
||||||
/// either side or which has had an I/O error will also cause a panic.
|
/// either side or which has had an I/O error will also cause a panic.
|
||||||
pub async fn accept_reset(mut self, barrier: &T) -> io::Result<AcceptedStream<Io>> {
|
pub async fn accept_reset<U: AsXml>(mut self, barrier: &U) -> io::Result<AcceptedStream<Io>> {
|
||||||
self.assert_retypable();
|
self.assert_retypable();
|
||||||
self.send(barrier).await?;
|
self.send(barrier).await?;
|
||||||
|
|
||||||
|
|
@ -361,7 +361,7 @@ impl<Io: AsyncBufRead + AsyncWrite + Unpin, T: FromXml + AsXml + fmt::Debug> Xml
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Io: AsyncBufRead, T: FromXml + AsXml + fmt::Debug> Stream for XmlStream<Io, T> {
|
impl<Io: AsyncBufRead, T: FromXml + fmt::Debug> Stream for XmlStream<Io, T> {
|
||||||
type Item = Result<T, ReadError>;
|
type Item = Result<T, ReadError>;
|
||||||
|
|
||||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||||
|
|
@ -401,7 +401,7 @@ impl<Io: AsyncBufRead, T: FromXml + AsXml + fmt::Debug> Stream for XmlStream<Io,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Io: AsyncWrite, T: FromXml + AsXml> XmlStream<Io, T> {
|
impl<Io: AsyncWrite, T: FromXml> XmlStream<Io, T> {
|
||||||
/// Initiate stream shutdown and poll for completion.
|
/// Initiate stream shutdown and poll for completion.
|
||||||
///
|
///
|
||||||
/// Please see [`Self::shutdown`] for details.
|
/// Please see [`Self::shutdown`] for details.
|
||||||
|
|
@ -443,7 +443,7 @@ impl<Io: AsyncWrite, T: FromXml + AsXml> XmlStream<Io, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Io: AsyncWrite + Unpin, T: FromXml + AsXml> XmlStream<Io, T> {
|
impl<Io: AsyncWrite + Unpin, T: FromXml> XmlStream<Io, T> {
|
||||||
/// Send the stream footer and close the sender side of the underlying
|
/// Send the stream footer and close the sender side of the underlying
|
||||||
/// transport.
|
/// transport.
|
||||||
///
|
///
|
||||||
|
|
@ -459,7 +459,7 @@ impl<Io: AsyncWrite + Unpin, T: FromXml + AsXml> XmlStream<Io, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'x, Io: AsyncWrite, T: FromXml + AsXml, U: AsXml> Sink<&'x U> for XmlStream<Io, T> {
|
impl<'x, Io: AsyncWrite, T: FromXml, U: AsXml> Sink<&'x U> for XmlStream<Io, T> {
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
|
@ -489,11 +489,11 @@ impl<'x, Io: AsyncWrite, T: FromXml + AsXml, U: AsXml> Sink<&'x U> for XmlStream
|
||||||
|
|
||||||
/// Future implementing [`XmlStream::shutdown`] using
|
/// Future implementing [`XmlStream::shutdown`] using
|
||||||
/// [`XmlStream::poll_shutdown`].
|
/// [`XmlStream::poll_shutdown`].
|
||||||
pub struct Shutdown<'a, Io: AsyncWrite, T: FromXml + AsXml> {
|
pub struct Shutdown<'a, Io: AsyncWrite, T: FromXml> {
|
||||||
stream: Pin<&'a mut XmlStream<Io, T>>,
|
stream: Pin<&'a mut XmlStream<Io, T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Io: AsyncWrite, T: FromXml + AsXml> Future for Shutdown<'_, Io, T> {
|
impl<Io: AsyncWrite, T: FromXml> Future for Shutdown<'_, Io, T> {
|
||||||
type Output = io::Result<()>;
|
type Output = io::Result<()>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use tokio::io::{AsyncBufRead, AsyncWrite};
|
||||||
|
|
||||||
use xmpp_parsers::{stream_error::StreamError, stream_features::StreamFeatures};
|
use xmpp_parsers::{stream_error::StreamError, stream_features::StreamFeatures};
|
||||||
|
|
||||||
use xso::{AsXml, FromXml};
|
use xso::FromXml;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
common::{RawXmlStream, StreamHeader},
|
common::{RawXmlStream, StreamHeader},
|
||||||
|
|
@ -78,7 +78,7 @@ impl<Io: AsyncBufRead + AsyncWrite + Unpin> PendingFeaturesSend<Io> {
|
||||||
/// After the stream features have been sent, the stream can be used for
|
/// After the stream features have been sent, the stream can be used for
|
||||||
/// exchanging stream-level elements (stanzas or "nonzas"). The Rust type
|
/// exchanging stream-level elements (stanzas or "nonzas"). The Rust type
|
||||||
/// for these elements must be given as type parameter `T`.
|
/// for these elements must be given as type parameter `T`.
|
||||||
pub async fn send_features<T: FromXml + AsXml>(
|
pub async fn send_features<T: FromXml>(
|
||||||
self,
|
self,
|
||||||
features: &'_ StreamFeatures,
|
features: &'_ StreamFeatures,
|
||||||
) -> io::Result<XmlStream<Io, T>> {
|
) -> io::Result<XmlStream<Io, T>> {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue