extern crate alloc;
use alloc::{boxed::Box, string::String, vec::Vec};
use core::future::Future;
use core::pin::Pin;
#[derive(Debug, Clone)]
pub struct ConnectorConfig {
pub qos: u8,
pub retain: bool,
pub timeout_ms: Option<u32>,
pub protocol_options: Vec<(String, String)>,
}
impl Default for ConnectorConfig {
fn default() -> Self {
Self {
qos: 0,
retain: false,
timeout_ms: Some(5000),
protocol_options: Vec::new(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PublishError {
ConnectionFailed,
MessageTooLarge,
UnsupportedQoS,
Timeout,
BufferFull,
InvalidDestination,
}
#[cfg(feature = "defmt")]
impl defmt::Format for PublishError {
fn format(&self, f: defmt::Formatter) {
match self {
Self::ConnectionFailed => defmt::write!(f, "ConnectionFailed"),
Self::MessageTooLarge => defmt::write!(f, "MessageTooLarge"),
Self::UnsupportedQoS => defmt::write!(f, "UnsupportedQoS"),
Self::Timeout => defmt::write!(f, "Timeout"),
Self::BufferFull => defmt::write!(f, "BufferFull"),
Self::InvalidDestination => defmt::write!(f, "InvalidDestination"),
}
}
}
#[cfg(feature = "std")]
impl std::fmt::Display for PublishError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ConnectionFailed => write!(f, "Failed to connect to endpoint"),
Self::MessageTooLarge => write!(f, "Message payload too large"),
Self::UnsupportedQoS => write!(f, "QoS level not supported"),
Self::Timeout => write!(f, "Operation timeout"),
Self::BufferFull => write!(f, "Buffer full, cannot queue message"),
Self::InvalidDestination => write!(f, "Invalid destination"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for PublishError {}
pub trait Connector: Send + Sync {
fn publish(
&self,
destination: &str,
config: &ConnectorConfig,
payload: &[u8],
) -> Pin<Box<dyn Future<Output = Result<(), PublishError>> + Send + '_>>;
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::sync::Arc;
struct MockConnector;
impl Connector for MockConnector {
fn publish(
&self,
_destination: &str,
_config: &ConnectorConfig,
_payload: &[u8],
) -> Pin<Box<dyn Future<Output = Result<(), PublishError>> + Send + '_>> {
Box::pin(async move { Ok(()) })
}
}
#[test]
fn test_connector_trait() {
let connector = Arc::new(MockConnector);
let _trait_obj: Arc<dyn Connector> = connector;
}
#[test]
fn test_connector_config_default() {
let config = ConnectorConfig::default();
assert_eq!(config.qos, 0);
assert!(!config.retain);
assert_eq!(config.timeout_ms, Some(5000));
assert_eq!(config.protocol_options.len(), 0);
}
#[test]
fn test_publish_error_copy() {
let err = PublishError::ConnectionFailed;
let err2 = err; assert_eq!(err, err2);
}
}