Skip to main content

shape_wire/transport/
mod.rs

1//! Transport abstraction for Shape inter-node communication.
2//!
3//! Provides a trait-based transport layer that decouples the wire format
4//! from the underlying network protocol. Implementations include TCP
5//! (always available) and QUIC (behind the `quic` feature flag).
6
7use std::sync::Arc;
8use std::time::Duration;
9
10/// Errors from transport operations.
11#[derive(Debug, thiserror::Error)]
12pub enum TransportError {
13    #[error("connection failed: {0}")]
14    ConnectionFailed(String),
15    #[error("send failed: {0}")]
16    SendFailed(String),
17    #[error("receive failed: {0}")]
18    ReceiveFailed(String),
19    #[error("timeout")]
20    Timeout,
21    #[error("connection closed")]
22    ConnectionClosed,
23    #[error("payload too large: {size} bytes (max {max})")]
24    PayloadTooLarge { size: usize, max: usize },
25    #[error("io error: {0}")]
26    Io(#[from] std::io::Error),
27}
28
29/// Core transport abstraction for Shape inter-node communication.
30///
31/// Implementations provide one-shot request/response (`send`) and
32/// persistent connection (`connect`) semantics.
33pub trait Transport: Send + Sync {
34    /// Send a payload to `destination` and return the response.
35    ///
36    /// This is a one-shot operation: connect, send, receive, close.
37    fn send(&self, destination: &str, payload: &[u8]) -> Result<Vec<u8>, TransportError>;
38
39    /// Establish a persistent connection to `destination`.
40    fn connect(&self, destination: &str) -> Result<Box<dyn Connection>, TransportError>;
41}
42
43/// A persistent, bidirectional connection to a remote node.
44pub trait Connection: Send {
45    /// Send a framed payload over the connection.
46    fn send(&mut self, payload: &[u8]) -> Result<(), TransportError>;
47
48    /// Receive a framed payload. If `timeout` is `None`, blocks indefinitely.
49    fn recv(&mut self, timeout: Option<Duration>) -> Result<Vec<u8>, TransportError>;
50
51    /// Close the connection gracefully.
52    fn close(&mut self) -> Result<(), TransportError>;
53
54    /// Whether this connection supports out-of-band sidecar delivery.
55    ///
56    /// When true, sidecars can be sent in parallel on separate streams
57    /// (e.g. QUIC unidirectional streams). When false, sidecars are sent
58    /// sequentially on the same connection via `send()`.
59    fn supports_sidecars(&self) -> bool {
60        false
61    }
62
63    /// Send a sidecar payload. Default: falls back to `send()`.
64    fn send_sidecar(&mut self, payload: &[u8]) -> Result<(), TransportError> {
65        self.send(payload)
66    }
67
68    /// Receive any incoming message (regular or sidecar). Default: falls back to `recv()`.
69    fn recv_any(&mut self, timeout: Option<Duration>) -> Result<Vec<u8>, TransportError> {
70        self.recv(timeout)
71    }
72}
73
74impl<T: Transport + ?Sized> Transport for Arc<T> {
75    fn send(&self, destination: &str, payload: &[u8]) -> Result<Vec<u8>, TransportError> {
76        self.as_ref().send(destination, payload)
77    }
78
79    fn connect(&self, destination: &str) -> Result<Box<dyn Connection>, TransportError> {
80        self.as_ref().connect(destination)
81    }
82}
83
84pub mod factory;
85pub mod framing;
86pub mod memoized;
87pub mod tcp;
88
89#[cfg(feature = "quic")]
90pub mod quic;