use std::fmt;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::str::FromStr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Address {
Network(SocketAddr),
Unix(PathBuf),
}
impl fmt::Display for Address {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Address::Network(addr) => write!(f, "{addr}"),
Address::Unix(path) => write!(f, "unix:{}", path.display()),
}
}
}
impl From<SocketAddr> for Address {
fn from(addr: SocketAddr) -> Self {
Address::Network(addr)
}
}
impl From<PathBuf> for Address {
fn from(path: PathBuf) -> Self {
Address::Unix(path)
}
}
impl From<&str> for Address {
fn from(s: &str) -> Self {
if let Some(stripped) = s.strip_prefix("unix:") {
Address::Unix(PathBuf::from(stripped))
} else {
Address::Network(s.parse().expect("Invalid socket address"))
}
}
}
impl FromStr for Address {
type Err = crate::EchoError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Some(stripped) = s.strip_prefix("unix:") {
Ok(Address::Unix(PathBuf::from(stripped)))
} else {
s.parse::<SocketAddr>()
.map(Address::Network)
.map_err(|e| crate::EchoError::Config(format!("Invalid socket address: {e}")))
}
}
}
impl Address {
pub fn is_network(&self) -> bool {
matches!(self, Address::Network(_))
}
pub fn is_unix(&self) -> bool {
matches!(self, Address::Unix(_))
}
pub fn as_network(&self) -> Option<&SocketAddr> {
match self {
Address::Network(addr) => Some(addr),
_ => None,
}
}
pub fn as_unix(&self) -> Option<&PathBuf> {
match self {
Address::Unix(path) => Some(path),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_network_address() {
let addr: Address = "127.0.0.1:8080".into();
assert!(addr.is_network());
assert!(!addr.is_unix());
assert!(addr.as_network().is_some());
assert!(addr.as_unix().is_none());
}
#[test]
fn test_unix_address() {
let addr: Address = "unix:/tmp/test.sock".into();
assert!(!addr.is_network());
assert!(addr.is_unix());
assert!(addr.as_network().is_none());
assert!(addr.as_unix().is_some());
}
#[test]
fn test_display() {
let net_addr: Address = "127.0.0.1:8080".into();
let unix_addr: Address = "unix:/tmp/test.sock".into();
assert_eq!(net_addr.to_string(), "127.0.0.1:8080");
assert_eq!(unix_addr.to_string(), "unix:/tmp/test.sock");
}
}