#![allow(clippy::init_numbered_fields)]
use std::net::{self, SocketAddr};
use std::str::FromStr;
use crate::node::NodeAddrParseError;
use crate::{AddrParseError, InetSocketAddr, NodeAddr};
#[derive(Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum ServerAddrParseError {
#[from]
#[display(inner)]
InvalidNode(NodeAddrParseError),
#[from]
#[display(inner)]
InvalidAddr(AddrParseError),
Unrecognized(String),
}
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
#[cfg_attr(feature = "strict_encoding", derive(StrictEncode, StrictDecode))]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
pub enum ServerAddr {
#[display("{0}", alt = "bronze://{0}")]
#[from]
Bronze(NodeAddr),
#[display("{0}", alt = "tcp://{0}")]
#[from]
Tcp(InetSocketAddr),
#[display("{0}", alt = "ipc://{0}")]
#[from]
Ipc(String),
}
impl FromStr for ServerAddr {
type Err = ServerAddrParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut split = s.split("://");
Ok(match (split.next(), split.next(), split.next()) {
(Some("bronze"), Some(s), None) => NodeAddr::from_str(s)?.into(),
(Some("tcp"), Some(s), None) => InetSocketAddr::from_str(s)?.into(),
(Some("ipc"), Some(s), None) => ServerAddr::Ipc(s.to_owned()),
(Some(s), None, _) => NodeAddr::from_str(s)
.map(ServerAddr::from)
.map_err(ServerAddrParseError::from)
.or_else(|_| {
InetSocketAddr::from_str(s)
.map(ServerAddr::from)
.map_err(ServerAddrParseError::from)
})
.unwrap_or_else(|_| ServerAddr::Ipc(s.to_owned())),
_ => return Err(ServerAddrParseError::Unrecognized(s.to_owned())),
})
}
}
#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum ServiceAddrParseError {
#[from]
#[display(inner)]
InvalidAddr(net::AddrParseError),
Unrecognized(String),
}
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
#[cfg_attr(feature = "strict_encoding", derive(StrictEncode, StrictDecode))]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
pub enum ServiceAddr {
#[display("{0}", alt = "tcp://{0}")]
#[from]
Tcp(SocketAddr),
#[display("{0}", alt = "ipc://{0}")]
Ipc(String),
#[display("{0}", alt = "inproc://{0}")]
Inproc(String),
}
impl FromStr for ServiceAddr {
type Err = ServiceAddrParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut split = s.split("://");
Ok(match (split.next(), split.next(), split.next()) {
(Some("tcp"), Some(s), None) => SocketAddr::from_str(s)?.into(),
(Some("ipc"), Some(s), None) => ServiceAddr::Ipc(s.to_owned()),
(Some("inproc"), Some(s), None) => {
ServiceAddr::Inproc(s.to_owned())
}
(Some(s), None, _) if s.contains('/') => {
ServiceAddr::Ipc(s.to_owned())
}
(Some(s), None, _) => SocketAddr::from_str(s)
.map(ServiceAddr::from)
.unwrap_or_else(|_| ServiceAddr::Inproc(s.to_owned())),
_ => return Err(ServiceAddrParseError::Unrecognized(s.to_owned())),
})
}
}
impl ServiceAddr {
pub fn zmq_connect_string(&self) -> String { format!("{self:#}") }
}