pubky_homeserver/data_directory/
domain_port.rs1use serde::{Deserialize, Serialize};
2use std::fmt::{self, Debug};
3use std::result::Result;
4use std::str::FromStr;
5
6use super::domain::Domain;
7
8#[derive(Clone, PartialEq)]
10pub struct DomainPort {
11 pub domain: Domain,
13 pub port: u16,
15}
16
17impl Debug for DomainPort {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 write!(f, "{}:{}", self.domain, self.port)
20 }
21}
22
23impl TryFrom<&str> for DomainPort {
24 type Error = anyhow::Error;
25
26 fn try_from(s: &str) -> Result<Self, Self::Error> {
27 Self::from_str(s)
28 }
29}
30
31impl fmt::Display for DomainPort {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "{}:{}", self.domain, self.port)
34 }
35}
36
37impl FromStr for DomainPort {
38 type Err = anyhow::Error;
39
40 fn from_str(s: &str) -> Result<Self, Self::Err> {
41 let parts: Vec<&str> = s.split(':').collect();
42 if parts.len() != 2 {
43 return Err(anyhow::anyhow!(
44 "Invalid domain:port format. Expected 'domain:port'"
45 ));
46 }
47 let part0 = parts[0];
48
49 let domain = part0.parse::<Domain>()?;
50 let port = parts[1].parse::<u16>()?;
51
52 Ok(Self { domain, port })
53 }
54}
55
56impl Serialize for DomainPort {
57 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
58 where
59 S: serde::Serializer,
60 {
61 serializer.serialize_str(&self.to_string())
62 }
63}
64
65impl<'de> Deserialize<'de> for DomainPort {
66 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67 where
68 D: serde::Deserializer<'de>,
69 {
70 let s = String::deserialize(deserializer)?;
71 Self::from_str(&s).map_err(|e| serde::de::Error::custom(e.to_string()))
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_domain_port_from_str() {
81 let domain_port = DomainPort::from_str("example.com:6286").unwrap();
82 assert_eq!(domain_port.domain.to_string(), "example.com");
83 assert_eq!(domain_port.port, 6286);
84 }
85
86 #[test]
87 fn test_domain_port_from_str_invalid1() {
88 let domain_port = DomainPort::from_str("example.com");
89 assert!(domain_port.is_err());
90 }
91
92 #[test]
93 fn test_domain_port_from_str_invalid2() {
94 let domain_port = DomainPort::from_str("example..com:80");
95 assert!(domain_port.is_err());
96 }
97}