use core::fmt::Display;
use std::io;
use std::path::PathBuf;
#[cfg(feature = "direct-serial")]
use crate::connection::direct_serial::config::SerialConfig;
use crate::connection::file::config::FileConfig;
#[cfg(feature = "tcp")]
use crate::connection::tcp::config::{TcpConfig, TcpMode};
#[cfg(feature = "udp")]
use crate::connection::udp::config::{UdpConfig, UdpMode};
pub enum ConnectionAddress {
#[cfg(feature = "tcp")]
Tcp(TcpConfig),
#[cfg(feature = "udp")]
Udp(UdpConfig),
#[cfg(feature = "direct-serial")]
Serial(SerialConfig),
File(FileConfig),
}
#[cfg(feature = "tcp")]
impl From<TcpConfig> for ConnectionAddress {
fn from(value: TcpConfig) -> Self {
Self::Tcp(value)
}
}
#[cfg(feature = "udp")]
impl From<UdpConfig> for ConnectionAddress {
fn from(value: UdpConfig) -> Self {
Self::Udp(value)
}
}
#[cfg(feature = "direct-serial")]
impl From<SerialConfig> for ConnectionAddress {
fn from(value: SerialConfig) -> Self {
Self::Serial(value)
}
}
impl From<FileConfig> for ConnectionAddress {
fn from(value: FileConfig) -> Self {
Self::File(value)
}
}
impl Display for ConnectionAddress {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
#[cfg(feature = "tcp")]
Self::Tcp(connectable) => write!(f, "{connectable}"),
#[cfg(feature = "udp")]
Self::Udp(connectable) => write!(f, "{connectable}"),
#[cfg(feature = "direct-serial")]
Self::Serial(connectable) => write!(f, "{connectable}"),
Self::File(connectable) => write!(f, "{connectable}"),
}
}
}
impl ConnectionAddress {
pub fn parse_address(address: &str) -> Result<Self, io::Error> {
let (protocol, address) = address.split_once(':').ok_or(io::Error::new(
io::ErrorKind::AddrNotAvailable,
"Protocol unsupported",
))?;
let conn = match protocol {
#[cfg(feature = "direct-serial")]
"serial" => {
let (port_name, baud) = address.split_once(':').ok_or(io::Error::new(
io::ErrorKind::AddrNotAvailable,
"Incomplete port settings",
))?;
Self::Serial(SerialConfig::new(
port_name.to_string(),
baud.parse().map_err(|_| {
io::Error::new(io::ErrorKind::AddrNotAvailable, "Invalid baud rate")
})?,
))
}
#[cfg(feature = "tcp")]
"tcpin" | "tcpout" => {
let mode = if protocol == "tcpout" {
TcpMode::TcpOut
} else {
TcpMode::TcpIn
};
Self::Tcp(TcpConfig::new(address.to_string(), mode))
}
#[cfg(feature = "udp")]
"udpin" | "udpout" | "udpcast" => Self::Udp(UdpConfig::new(
address.to_string(),
match protocol {
"udpin" => UdpMode::Udpin,
"udpout" => UdpMode::Udpout,
"udpcast" => UdpMode::Udpcast,
_ => unreachable!(),
},
)),
"file" => Self::File(FileConfig::new(PathBuf::from(address))),
_ => {
return Err(io::Error::new(
io::ErrorKind::AddrNotAvailable,
"Protocol unsupported",
))
}
};
Ok(conn)
}
}