Skip to main content

ma_core/
outbox.rs

1//! Transport-agnostic send handle to a remote ma service.
2//!
3//! An `Outbox` wraps the transport details and exposes only
4//! `send()` + `close()`. Created via [`crate::iroh::IrohEndpoint::outbox`].
5//!
6//! `send()` takes a [`Message`], validates it,
7//! serializes to CBOR, and transmits. Malformed or expired messages
8//! are rejected before anything hits the wire.
9//!
10//! Requires the `iroh` feature.
11//!
12//! ```ignore
13//! let mut outbox = ep.outbox("did:ma:456", "ma/presence/0.0.1").await?;
14//! outbox.send(&message).await?;
15//! outbox.close();
16//! ```
17
18use crate::error::Result;
19use crate::iroh::channel::Channel;
20use did_ma::Message;
21
22/// A transport-agnostic write handle to a remote service.
23///
24/// The caller doesn't need to know the underlying transport.
25#[derive(Debug)]
26pub struct Outbox {
27    inner: OutboxTransport,
28    did: String,
29    protocol: String,
30}
31
32#[derive(Debug)]
33enum OutboxTransport {
34    Channel(Channel),
35}
36
37impl Outbox {
38    /// Create an outbox backed by a channel.
39    pub(crate) fn from_channel(channel: Channel, did: String, protocol: String) -> Self {
40        Self {
41            inner: OutboxTransport::Channel(channel),
42            did,
43            protocol,
44        }
45    }
46
47    /// Send a ma message to the remote service.
48    ///
49    /// Validates the message headers, serializes to CBOR, and transmits.
50    ///
51    /// # Errors
52    /// Returns an error if validation, serialization, or transport send fails.
53    pub async fn send(&mut self, message: &Message) -> Result<()> {
54        message.headers().validate()?;
55        let cbor = message.to_cbor()?;
56        match &mut self.inner {
57            OutboxTransport::Channel(channel) => channel.send(&cbor).await,
58        }
59    }
60
61    /// The DID this outbox delivers to.
62    #[must_use]
63    pub fn did(&self) -> &str {
64        &self.did
65    }
66
67    /// The protocol this outbox is connected to.
68    #[must_use]
69    pub fn protocol(&self) -> &str {
70        &self.protocol
71    }
72
73    /// Close the outbox gracefully.
74    pub fn close(self) {
75        match self.inner {
76            OutboxTransport::Channel(channel) => channel.close(),
77        }
78    }
79}