use crate::multistream::Negotiator;
use crate::transport::TransportError;
use crate::upgrade::{ProtocolName, Upgrader};
use futures::{AsyncRead, AsyncWrite};
use log::{debug, trace};
#[derive(Debug, Clone)]
pub(crate) struct Multistream<U> {
inner: U,
}
impl<U> Multistream<U> {
pub fn new(inner: U) -> Self {
Self { inner }
}
}
impl<U> Multistream<U> {
pub(crate) async fn select_inbound<C>(self, socket: C) -> Result<U::Output, TransportError>
where
C: AsyncRead + AsyncWrite + Unpin,
U: Upgrader<C> + Send,
{
trace!("starting multistream select for inbound...");
let protocols = self.inner.protocol_info();
let neg = Negotiator::new_with_protocols(protocols.into_iter().map(NameWrap as fn(_) -> NameWrap<_>));
let (proto, socket) = neg.negotiate(socket).await?;
debug!("select_inbound {:?}", proto);
self.inner.upgrade_inbound(socket, proto.0).await
}
pub(crate) async fn select_outbound<C: Send + Unpin>(self, socket: C) -> Result<U::Output, TransportError>
where
C: AsyncRead + AsyncWrite + Unpin,
U: Upgrader<C> + Send,
{
trace!("starting multistream select for outbound...");
let protocols = self.inner.protocol_info();
let neg = Negotiator::new_with_protocols(protocols.into_iter().map(NameWrap as fn(_) -> NameWrap<_>));
let (proto, socket) = neg.select_one(socket).await?;
debug!("select_outbound {:?}", proto);
self.inner.upgrade_outbound(socket, proto.0).await
}
}
#[derive(Clone)]
struct NameWrap<N>(N);
impl<N: ProtocolName> AsRef<[u8]> for NameWrap<N> {
fn as_ref(&self) -> &[u8] {
self.0.protocol_name()
}
}
impl<N: ProtocolName> std::fmt::Debug for NameWrap<N> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", String::from_utf8_lossy(self.0.protocol_name()))
}
}
#[cfg(test)]
mod tests {
#[test]
fn to_be_done() {}
}