1use std::borrow::Borrow;
23use std::fmt::{self, Debug, Display, Formatter};
24use std::io;
25use std::net::{self, ToSocketAddrs};
26use std::str::FromStr;
27
28use cypher::EcPk;
29
30use crate::{Addr, AddrParseError, Host, NetAddr, PartialAddr, ToSocketAddr};
31
32#[derive(Debug, Display, Error, From)]
33#[display(doc_comments)]
34pub enum PeerAddrParseError<Id: Debug>
35where
36 Id: FromStr,
37 <Id as FromStr>::Err: std::error::Error,
38{
39 #[from]
40 #[from(net::AddrParseError)]
41 #[display(inner)]
42 Addr(AddrParseError),
43
44 Key(<Id as FromStr>::Err),
46
47 InvalidFormat,
50}
51
52#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
53pub struct PeerAddr<Id: EcPk, A: Addr> {
54 pub id: Id,
55 pub addr: A,
56}
57
58impl<Id: EcPk, A: Addr> PeerAddr<Id, A> {
59 pub fn new(id: Id, addr: A) -> Self { Self { id, addr } }
60}
61
62impl<Id: EcPk, A: Addr> Borrow<Id> for PeerAddr<Id, A> {
63 fn borrow(&self) -> &Id { &self.id }
64}
65
66impl<Id: EcPk, A: Addr> Host for PeerAddr<Id, A> {
67 fn requires_proxy(&self) -> bool { self.addr.requires_proxy() }
68}
69
70impl<Id: EcPk, A: Addr> Addr for PeerAddr<Id, A> {
71 fn port(&self) -> u16 { self.addr.port() }
72}
73
74impl<Id: EcPk, A: Addr + ToSocketAddr> ToSocketAddr for PeerAddr<Id, A> {
75 fn to_socket_addr(&self) -> net::SocketAddr { self.addr.to_socket_addr() }
76}
77
78impl<Id: EcPk, A: Addr> Display for PeerAddr<Id, A>
79where
80 Id: Display,
81 A: Display,
82{
83 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}@{}", self.id, self.addr) }
84}
85
86impl<Id: EcPk, A: Addr> FromStr for PeerAddr<Id, A>
87where
88 Id: FromStr + Debug,
89 <Id as FromStr>::Err: std::error::Error,
90 A: FromStr,
91 <A as FromStr>::Err: Into<PeerAddrParseError<Id>>,
92{
93 type Err = PeerAddrParseError<Id>;
94
95 fn from_str(s: &str) -> Result<Self, Self::Err> {
96 if let Some((pk, addr)) = s.split_once('@') {
97 Ok(PeerAddr {
98 id: Id::from_str(pk).map_err(PeerAddrParseError::Key)?,
99 addr: A::from_str(addr).map_err(<A as FromStr>::Err::into)?,
100 })
101 } else {
102 Err(PeerAddrParseError::InvalidFormat)
103 }
104 }
105}
106
107impl<Id: EcPk, H: Host, const DEFAULT_PORT: u16> From<PeerAddr<Id, PartialAddr<H, DEFAULT_PORT>>>
108 for PeerAddr<Id, NetAddr<H>>
109{
110 fn from(peer: PeerAddr<Id, PartialAddr<H, DEFAULT_PORT>>) -> Self {
111 PeerAddr {
112 addr: peer.addr.into(),
113 id: peer.id,
114 }
115 }
116}
117
118impl<Id: EcPk, A: Addr, To: Host> From<PeerAddr<Id, A>> for NetAddr<To>
119where NetAddr<To>: From<A>
120{
121 fn from(peer: PeerAddr<Id, A>) -> Self { peer.addr.into() }
122}
123
124impl<Id: EcPk, A: Addr + Into<net::SocketAddr>> From<PeerAddr<Id, A>> for net::SocketAddr {
125 fn from(peer: PeerAddr<Id, A>) -> Self { peer.addr.into() }
126}
127
128impl<Id: EcPk, A: Addr> PeerAddr<Id, A> {
129 pub fn with(id: impl Into<Id>, addr: impl Into<A>) -> Self {
130 PeerAddr {
131 id: id.into(),
132 addr: addr.into(),
133 }
134 }
135}
136
137impl<Id: EcPk, A> ToSocketAddrs for PeerAddr<Id, A>
138where A: Addr + ToSocketAddrs
139{
140 type Iter = A::Iter;
141
142 fn to_socket_addrs(&self) -> io::Result<A::Iter> { self.addr.to_socket_addrs() }
143}