1use std::fmt::{self, Display, Formatter};
15use std::str::FromStr;
16
17use internet2::addr::{
18 AddrParseError, NodeAddr, NodeAddrParseError, PartialNodeAddr,
19};
20#[cfg(feature = "bifrost")]
21use p2p::bifrost::LNP2P_BIFROST_PORT;
22#[cfg(feature = "bolt")]
23use p2p::bolt::LNP2P_BOLT_PORT;
24use p2p::Protocol;
25
26#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Hash, Debug)]
30#[derive(NetworkEncode, NetworkDecode)]
31pub struct LnpAddr {
32 pub protocol: Protocol,
34
35 pub node_addr: NodeAddr,
37}
38
39impl LnpAddr {
40 #[cfg(feature = "bolt")]
41 pub fn bolt(addr: PartialNodeAddr) -> LnpAddr {
43 LnpAddr {
44 protocol: Protocol::Bolt,
45 node_addr: addr.node_addr(LNP2P_BOLT_PORT),
46 }
47 }
48
49 #[cfg(feature = "bifrost")]
50 pub fn bifrost(addr: PartialNodeAddr) -> LnpAddr {
52 LnpAddr {
53 protocol: Protocol::Bifrost,
54 node_addr: addr.node_addr(LNP2P_BIFROST_PORT),
55 }
56 }
57
58 pub fn port(self) -> u16 {
60 self.node_addr
61 .addr
62 .port()
63 .expect("port information always present in NodeAddr")
64 }
65}
66
67impl Display for LnpAddr {
68 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
69 write!(
70 f,
71 "{}://{}@{}",
72 self.protocol,
73 self.node_addr.id,
74 self.node_addr.addr.address()
75 )?;
76 if self.protocol.default_port() != self.port() {
77 write!(f, ":{}", self.port())?;
78 }
79 Ok(())
80 }
81}
82
83impl FromStr for LnpAddr {
84 type Err = NodeAddrParseError;
85
86 fn from_str(s: &str) -> Result<Self, Self::Err> {
87 let mut split = s.split("://");
88 match (
89 split.next().map(str::to_lowercase).as_deref(),
90 split.next(),
91 split.next(),
92 ) {
93 #[cfg(feature = "bolt")]
94 (Some("bolt"), Some(addr), None) => {
95 PartialNodeAddr::from_str(addr).map(LnpAddr::bolt)
96 }
97 #[cfg(feature = "bifrost")]
98 (Some("bifrost"), Some(addr), None) => {
99 PartialNodeAddr::from_str(addr).map(LnpAddr::bifrost)
100 }
101 (Some(unknown), ..) => {
102 Err(AddrParseError::UnknownProtocolError(unknown.to_owned())
103 .into())
104 }
105 _ => Err(AddrParseError::WrongAddrFormat(s.to_owned()).into()),
106 }
107 }
108}