arachnid_cli/config/types/
netaddr.rs

1/*
2    Appellation: server_addr <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5
6fn default_ip() -> String {
7    core::net::IpAddr::V4(core::net::Ipv4Addr::LOCALHOST).to_string()
8}
9
10const fn default_port() -> u16 {
11    NetAddr::DEFAULT_PORT
12}
13
14#[derive(
15    Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize,
16)]
17#[serde(default)]
18pub struct NetAddr {
19    #[serde(default = "default_ip")]
20    pub host: String,
21    #[serde(default = "default_port")]
22    pub port: u16,
23}
24
25impl NetAddr {
26    pub const LOCALHOST: &'static str = "0.0.0.0";
27    pub const DEFAULT_HOST: &'static str = "0.0.0.0";
28    pub const DEFAULT_PORT: u16 = 8080;
29
30    /// initialize a new instance of the network address from the given components
31    pub fn new<H>(host: H, port: u16) -> Self
32    where
33        H: ToString,
34    {
35        Self {
36            host: host.to_string(),
37            port,
38        }
39    }
40
41    pub fn from_ip_with_port(ip: core::net::IpAddr, port: u16) -> Self {
42        Self {
43            host: ip.to_string(),
44            port,
45        }
46    }
47    /// convert the given socket address into a valid network address
48    pub fn from_socket_addr(addr: core::net::SocketAddr) -> Self {
49        Self {
50            host: addr.ip().to_string(),
51            port: addr.port(),
52        }
53    }
54    /// initialize a new instance of the network address bound to localhost and the given port
55    pub fn localhost(port: u16) -> Self {
56        Self {
57            host: Self::LOCALHOST.to_string(),
58            port,
59        }
60    }
61    /// convert a reference of the network address into a [`SocketAddr`](core::net::SocketAddr)
62    pub fn as_socket_addr(&self) -> core::net::SocketAddr {
63        self.to_string().parse().unwrap()
64    }
65    /// initialize a new listener, bound to the configured address
66    pub async fn bind(&self) -> std::io::Result<tokio::net::TcpListener> {
67        tokio::net::TcpListener::bind(&self.as_socket_addr()).await
68    }
69    /// returns the ip of the address
70    pub fn ip(&self) -> core::net::IpAddr {
71        self.as_socket_addr().ip()
72    }
73    /// returns the host
74    pub fn host(&self) -> &str {
75        &self.host
76    }
77    /// returns a copy to the port
78    pub fn port(&self) -> u16 {
79        self.port
80    }
81    /// update the host of the address
82    pub fn set_host<T>(&mut self, host: T)
83    where
84        T: ToString,
85    {
86        self.host = host.to_string();
87    }
88    /// update the port of the address
89    pub fn set_port(&mut self, port: u16) {
90        self.port = port;
91    }
92    /// consumes the address to create another with the given host
93    pub fn with_host<T>(self, host: T) -> Self
94    where
95        T: ToString,
96    {
97        Self {
98            host: host.to_string(),
99            ..self
100        }
101    }
102    /// consumes the address to create another with the given port
103    pub fn with_port(self, port: u16) -> Self {
104        Self { port, ..self }
105    }
106}
107
108impl Default for NetAddr {
109    fn default() -> Self {
110        Self::localhost(Self::DEFAULT_PORT)
111    }
112}
113
114impl core::fmt::Display for NetAddr {
115    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
116        write!(f, "{host}:{port}", host = self.host, port = self.port)
117    }
118}
119
120impl core::str::FromStr for NetAddr {
121    type Err = anyhow::Error;
122
123    fn from_str(s: &str) -> Result<Self, Self::Err> {
124        // parse as a url to get the scheme, host and port
125        let url = s.parse::<url::Url>()?;
126        let host = url.host_str().expect("Failed to parse host");
127        let port = url.port().expect("failed to parse port");
128
129        let res = Self {
130            host: host.to_string(),
131            port,
132        };
133        Ok(res)
134    }
135}
136
137impl From<core::net::SocketAddr> for NetAddr {
138    fn from(addr: core::net::SocketAddr) -> Self {
139        Self::from_socket_addr(addr)
140    }
141}