use async_trait::async_trait;
use bytes::Bytes;
use std::fmt::Debug;
use crate::error::TransportResult;
pub mod arc;
pub mod channel;
pub mod shared_memory;
pub mod tcp;
pub mod utils;
#[cfg(unix)]
pub mod unix;
pub use utils::spawn_weak_loop;
#[async_trait]
pub trait FrameTransport: Send + Sync + Debug {
async fn send_frame(&self, data: &[u8]) -> TransportResult<()>;
async fn recv_frame(&self) -> TransportResult<Bytes>;
fn is_connected(&self) -> bool;
fn is_healthy(&self) -> bool {
true
}
async fn close(&self) -> TransportResult<()>;
fn stats(&self) -> Option<TransportStats> {
None
}
fn name(&self) -> &str {
"unknown"
}
}
#[derive(Debug, Clone, Default)]
pub struct TransportStats {
pub messages_sent: u64,
pub messages_received: u64,
pub bytes_sent: u64,
pub bytes_received: u64,
pub send_errors: u64,
pub recv_errors: u64,
pub avg_latency_us: Option<u64>,
}
impl TransportStats {
pub fn new() -> Self {
Self::default()
}
pub fn merge(&mut self, other: &TransportStats) {
self.messages_sent += other.messages_sent;
self.messages_received += other.messages_received;
self.bytes_sent += other.bytes_sent;
self.bytes_received += other.bytes_received;
self.send_errors += other.send_errors;
self.recv_errors += other.recv_errors;
if let (Some(our_latency), Some(other_latency)) =
(self.avg_latency_us, other.avg_latency_us)
{
self.avg_latency_us = Some((our_latency + other_latency) / 2);
} else if other.avg_latency_us.is_some() {
self.avg_latency_us = other.avg_latency_us;
}
}
}
impl std::fmt::Display for TransportStats {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Transport Statistics:")?;
writeln!(f, " Messages sent: {}", self.messages_sent)?;
writeln!(f, " Messages received: {}", self.messages_received)?;
writeln!(f, " Bytes sent: {}", self.bytes_sent)?;
writeln!(f, " Bytes received: {}", self.bytes_received)?;
writeln!(f, " Send errors: {}", self.send_errors)?;
writeln!(f, " Receive errors: {}", self.recv_errors)?;
if let Some(latency) = self.avg_latency_us {
writeln!(f, " Avg latency: {}μs", latency)?;
}
Ok(())
}
}
#[async_trait]
impl<T: FrameTransport + ?Sized> FrameTransport for std::sync::Arc<T> {
async fn send_frame(&self, data: &[u8]) -> TransportResult<()> {
(**self).send_frame(data).await
}
async fn recv_frame(&self) -> TransportResult<Bytes> {
(**self).recv_frame().await
}
fn is_connected(&self) -> bool {
(**self).is_connected()
}
fn is_healthy(&self) -> bool {
(**self).is_healthy()
}
async fn close(&self) -> TransportResult<()> {
(**self).close().await
}
fn stats(&self) -> Option<TransportStats> {
(**self).stats()
}
fn name(&self) -> &str {
(**self).name()
}
}
#[async_trait]
impl<T: FrameTransport + ?Sized> FrameTransport for Box<T> {
async fn send_frame(&self, data: &[u8]) -> TransportResult<()> {
(**self).send_frame(data).await
}
async fn recv_frame(&self) -> TransportResult<Bytes> {
(**self).recv_frame().await
}
fn is_connected(&self) -> bool {
(**self).is_connected()
}
fn is_healthy(&self) -> bool {
(**self).is_healthy()
}
async fn close(&self) -> TransportResult<()> {
(**self).close().await
}
fn stats(&self) -> Option<TransportStats> {
(**self).stats()
}
fn name(&self) -> &str {
(**self).name()
}
}
#[deprecated(since = "0.2.0", note = "Use FrameTransport instead")]
pub trait Transport: FrameTransport {}
#[allow(deprecated)]
impl<T: FrameTransport> Transport for T {}