#![no_std]
#![forbid(unsafe_code)]
#![warn(missing_docs)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
use core::fmt;
pub use zerodds_rtps::wire_types::Locator;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum SendError {
PayloadTooLarge {
size: usize,
limit: usize,
},
UnsupportedLocator,
Io {
message: &'static str,
},
}
impl fmt::Display for SendError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::PayloadTooLarge { size, limit } => {
write!(f, "transport payload too large: {size} > {limit}")
}
Self::UnsupportedLocator => f.write_str("transport: unsupported locator"),
Self::Io { message } => write!(f, "transport I/O error: {message}"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for SendError {}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum RecvError {
Timeout,
BufferTooSmall {
datagram_size: usize,
buffer_size: usize,
},
Io {
message: &'static str,
},
}
impl fmt::Display for RecvError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Timeout => f.write_str("transport recv timeout"),
Self::BufferTooSmall {
datagram_size,
buffer_size,
} => {
write!(
f,
"recv buffer too small: datagram {datagram_size} > buffer {buffer_size}"
)
}
Self::Io { message } => write!(f, "transport I/O error: {message}"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for RecvError {}
#[cfg(feature = "alloc")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReceivedDatagram {
pub source: Locator,
pub data: Vec<u8>,
}
#[cfg(feature = "alloc")]
pub trait Transport {
fn send(&self, dest: &Locator, data: &[u8]) -> Result<(), SendError>;
fn recv(&self) -> Result<ReceivedDatagram, RecvError>;
fn local_locator(&self) -> Locator;
}
#[cfg(test)]
mod tests {
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
use alloc::format;
use super::*;
#[cfg(feature = "alloc")]
#[test]
fn send_error_display_payload_too_large() {
let e = SendError::PayloadTooLarge {
size: 70_000,
limit: 65_535,
};
let s = format!("{e}");
assert!(s.contains("70000"));
assert!(s.contains("65535"));
}
#[cfg(feature = "alloc")]
#[test]
fn send_error_display_unsupported_locator() {
let s = format!("{}", SendError::UnsupportedLocator);
assert!(s.contains("unsupported"));
}
#[cfg(feature = "alloc")]
#[test]
fn send_error_display_io() {
let s = format!(
"{}",
SendError::Io {
message: "ENETDOWN"
}
);
assert!(s.contains("ENETDOWN"));
}
#[cfg(feature = "alloc")]
#[test]
fn recv_error_display_timeout() {
let s = format!("{}", RecvError::Timeout);
assert!(s.contains("timeout"));
}
#[cfg(feature = "alloc")]
#[test]
fn recv_error_display_buffer_too_small() {
let s = format!(
"{}",
RecvError::BufferTooSmall {
datagram_size: 1500,
buffer_size: 1024
}
);
assert!(s.contains("1500"));
assert!(s.contains("1024"));
}
#[cfg(feature = "alloc")]
#[test]
fn received_datagram_is_constructable() {
let r = ReceivedDatagram {
source: Locator::INVALID,
data: alloc::vec![1, 2, 3],
};
assert_eq!(r.data, alloc::vec![1, 2, 3]);
}
}