1#![allow(clippy::init_numbered_fields)]
15
16use std::net::{self, SocketAddr};
17use std::str::FromStr;
18
19use crate::node::NodeAddrParseError;
20use crate::{AddrParseError, InetSocketAddr, NodeAddr};
21
22#[derive(Debug, Display, Error, From)]
24#[display(doc_comments)]
25pub enum ServerAddrParseError {
26 #[from]
28 #[display(inner)]
29 InvalidNode(NodeAddrParseError),
30
31 #[from]
33 #[display(inner)]
34 InvalidAddr(AddrParseError),
35
36 Unrecognized(String),
38}
39
40#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
43#[cfg_attr(feature = "strict_encoding", derive(StrictEncode, StrictDecode))]
44#[cfg_attr(
45 feature = "serde",
46 derive(Serialize, Deserialize),
47 serde(crate = "serde_crate")
48)]
49pub enum ServerAddr {
50 #[display("{0}", alt = "bronze://{0}")]
52 #[from]
53 Bronze(NodeAddr),
54
55 #[display("{0}", alt = "tcp://{0}")]
57 #[from]
58 Tcp(InetSocketAddr),
59
60 #[display("{0}", alt = "ipc://{0}")]
62 #[from]
63 Ipc(String),
64}
65
66impl FromStr for ServerAddr {
67 type Err = ServerAddrParseError;
68
69 fn from_str(s: &str) -> Result<Self, Self::Err> {
70 let mut split = s.split("://");
71 Ok(match (split.next(), split.next(), split.next()) {
72 (Some("bronze"), Some(s), None) => NodeAddr::from_str(s)?.into(),
73 (Some("tcp"), Some(s), None) => InetSocketAddr::from_str(s)?.into(),
74 (Some("ipc"), Some(s), None) => ServerAddr::Ipc(s.to_owned()),
75 (Some(s), None, _) => NodeAddr::from_str(s)
76 .map(ServerAddr::from)
77 .map_err(ServerAddrParseError::from)
78 .or_else(|_| {
79 InetSocketAddr::from_str(s)
80 .map(ServerAddr::from)
81 .map_err(ServerAddrParseError::from)
82 })
83 .unwrap_or_else(|_| ServerAddr::Ipc(s.to_owned())),
84 _ => return Err(ServerAddrParseError::Unrecognized(s.to_owned())),
85 })
86 }
87}
88
89#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)]
91#[display(doc_comments)]
92pub enum ServiceAddrParseError {
93 #[from]
95 #[display(inner)]
96 InvalidAddr(net::AddrParseError),
97
98 Unrecognized(String),
100}
101
102#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, From)]
105#[cfg_attr(feature = "strict_encoding", derive(StrictEncode, StrictDecode))]
106#[cfg_attr(
107 feature = "serde",
108 derive(Serialize, Deserialize),
109 serde(crate = "serde_crate")
110)]
111pub enum ServiceAddr {
112 #[display("{0}", alt = "tcp://{0}")]
114 #[from]
115 Tcp(SocketAddr),
116
117 #[display("{0}", alt = "ipc://{0}")]
119 Ipc(String),
120
121 #[display("{0}", alt = "inproc://{0}")]
123 Inproc(String),
124}
125
126impl FromStr for ServiceAddr {
127 type Err = ServiceAddrParseError;
128
129 fn from_str(s: &str) -> Result<Self, Self::Err> {
130 let mut split = s.split("://");
131 Ok(match (split.next(), split.next(), split.next()) {
132 (Some("tcp"), Some(s), None) => SocketAddr::from_str(s)?.into(),
133 (Some("ipc"), Some(s), None) => ServiceAddr::Ipc(s.to_owned()),
134 (Some("inproc"), Some(s), None) => {
135 ServiceAddr::Inproc(s.to_owned())
136 }
137 (Some(s), None, _) if s.contains('/') => {
138 ServiceAddr::Ipc(s.to_owned())
139 }
140 (Some(s), None, _) => SocketAddr::from_str(s)
141 .map(ServiceAddr::from)
142 .unwrap_or_else(|_| ServiceAddr::Inproc(s.to_owned())),
143 _ => return Err(ServiceAddrParseError::Unrecognized(s.to_owned())),
144 })
145 }
146}
147
148impl ServiceAddr {
149 pub fn zmq_connect_string(&self) -> String { format!("{self:#}") }
151}