#[cfg(feature = "std")]
use std::error::Error;
#[cfg(feature = "std")]
use std::fmt;
#[cfg(not(feature = "std"))]
use core::fmt;
#[cfg(feature = "std")]
use std::net::SocketAddr;
#[cfg(not(feature = "std"))]
use alloc::{string::String, vec::Vec};
#[cfg(feature = "std")]
pub type Result<T> = std::result::Result<T, DataLinkError>;
#[cfg(not(feature = "std"))]
pub type Result<T> = core::result::Result<T, DataLinkError>;
#[derive(Debug)]
pub enum DataLinkError {
#[cfg(feature = "std")]
IoError(std::io::Error),
InvalidFrame,
CrcError,
AddressError(String),
UnsupportedType,
}
impl fmt::Display for DataLinkError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
#[cfg(feature = "std")]
DataLinkError::IoError(e) => write!(f, "I/O error: {}", e),
DataLinkError::InvalidFrame => write!(f, "Invalid frame format"),
DataLinkError::CrcError => write!(f, "CRC check failed"),
DataLinkError::AddressError(msg) => write!(f, "Address error: {}", msg),
DataLinkError::UnsupportedType => write!(f, "Unsupported data link type"),
}
}
}
#[cfg(feature = "std")]
impl Error for DataLinkError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DataLinkType {
BacnetIp,
Ethernet,
MsTP,
PointToPoint,
Arcnet,
}
pub trait DataLink: Send + Sync {
fn send_frame(&mut self, frame: &[u8], dest: &DataLinkAddress) -> Result<()>;
fn receive_frame(&mut self) -> Result<(Vec<u8>, DataLinkAddress)>;
fn link_type(&self) -> DataLinkType;
fn local_address(&self) -> DataLinkAddress;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DataLinkAddress {
#[cfg(feature = "std")]
Ip(SocketAddr),
Ethernet([u8; 6]),
MsTP(u8),
Broadcast,
}
pub mod bip;
pub mod ethernet;
pub mod mstp;
pub mod validation;
#[cfg(feature = "std")]
pub use bip::BacnetIpDataLink;
#[cfg(feature = "std")]
pub use ethernet::EthernetDataLink;
#[cfg(feature = "std")]
pub use mstp::MstpDataLink;