vox-core 0.10.0-rc.2

Core implementations for Vox connections, lanes, drivers, and links
Documentation
//! `LinkSource` and `Attachment`: how the connection machinery is given the
//! transport link it should use.
//!
//! This is a small abstraction over "give me a link once", kept as a trait
//! so the existing connection API composes with tests and production sockets.

use std::future::Future;

use vox_types::{Link, MaybeSend, PeerEvidence};

/// One transport attachment consumed by [`LinkSource::next_link`].
pub struct Attachment<L> {
    link: L,
    peer_evidence: PeerEvidence,
}

impl<L> Attachment<L> {
    /// Build an attachment around a single ready-to-use link.
    pub fn initiator(link: L) -> Self {
        Self {
            link,
            peer_evidence: PeerEvidence::none(),
        }
    }

    /// Attach locally asserted evidence supplied by the transport or embedding runtime.
    // r[impl connection.evidence]
    pub fn with_runtime_evidence(mut self, evidence: PeerEvidence) -> Self {
        self.peer_evidence = evidence;
        self
    }

    #[must_use]
    pub fn peer_evidence(&self) -> &PeerEvidence {
        &self.peer_evidence
    }

    pub fn into_link(self) -> L {
        self.link
    }

    pub fn into_parts(self) -> (L, PeerEvidence) {
        (self.link, self.peer_evidence)
    }
}

/// Source of transport links.
pub trait LinkSource: MaybeSend + 'static {
    type Link: Link + MaybeSend;

    fn next_link(
        &mut self,
    ) -> impl Future<Output = std::io::Result<Attachment<Self::Link>>> + MaybeSend + '_;
}

/// One-shot link source: hands out its single attachment, then errors on
/// every subsequent call.
pub struct SingleAttachmentSource<L> {
    attachment: Option<Attachment<L>>,
}

pub fn single_attachment_source<L: Link + MaybeSend + 'static>(
    attachment: Attachment<L>,
) -> SingleAttachmentSource<L> {
    SingleAttachmentSource {
        attachment: Some(attachment),
    }
}

pub fn single_link_source<L: Link + MaybeSend + 'static>(link: L) -> SingleAttachmentSource<L> {
    single_attachment_source(Attachment::initiator(link))
}

impl<L: Link + MaybeSend + 'static> LinkSource for SingleAttachmentSource<L> {
    type Link = L;

    async fn next_link(&mut self) -> std::io::Result<Attachment<Self::Link>> {
        self.attachment.take().ok_or_else(|| {
            std::io::Error::new(
                std::io::ErrorKind::ConnectionRefused,
                "single-use LinkSource exhausted",
            )
        })
    }
}