1use std::{convert::TryFrom, fmt, str::FromStr};
4
5use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
6
7use koibumi_core::net::SocketAddrExt;
8use koibumi_net::{
9 domain::{ParseSocketDomainError, SocketDomain},
10 socks::SocketAddr as SocksSocketAddr,
11};
12
13#[derive(Clone, PartialEq, Eq, Hash, Debug)]
15pub enum SocketAddrNode {
16 AddrExt(SocketAddrExt),
18 Domain(SocketDomain),
20}
21
22impl fmt::Display for SocketAddrNode {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match self {
25 Self::AddrExt(addr) => addr.fmt(f),
26 Self::Domain(domain) => domain.fmt(f),
27 }
28 }
29}
30
31impl Serialize for SocketAddrNode {
32 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
33 where
34 S: Serializer,
35 {
36 serializer.serialize_str(&self.to_string())
37 }
38}
39
40impl<'de> Deserialize<'de> for SocketAddrNode {
41 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
42 where
43 D: Deserializer<'de>,
44 {
45 let s = String::deserialize(deserializer)?;
46 s.parse().map_err(de::Error::custom)
47 }
48}
49
50impl From<SocketAddrExt> for SocketAddrNode {
51 fn from(addr: SocketAddrExt) -> Self {
52 Self::AddrExt(addr)
53 }
54}
55
56impl From<SocketDomain> for SocketAddrNode {
57 fn from(domain: SocketDomain) -> Self {
58 Self::Domain(domain)
59 }
60}
61
62#[derive(Clone, PartialEq, Eq, Debug)]
68pub enum TryFromSocketAddrNodeError {
69 Domain(SocketDomain),
71}
72
73impl fmt::Display for TryFromSocketAddrNodeError {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 Self::Domain(domain) => write!(
77 f,
78 "could not convert {} to an extended socket address",
79 domain
80 ),
81 }
82 }
83}
84
85impl std::error::Error for TryFromSocketAddrNodeError {}
86
87impl TryFrom<SocketAddrNode> for SocketAddrExt {
88 type Error = TryFromSocketAddrNodeError;
89
90 fn try_from(addr: SocketAddrNode) -> Result<Self, <Self as TryFrom<SocketAddrNode>>::Error> {
91 match addr {
92 SocketAddrNode::AddrExt(addr) => Ok(addr),
93 SocketAddrNode::Domain(domain) => Err(TryFromSocketAddrNodeError::Domain(domain)),
94 }
95 }
96}
97
98#[derive(Clone, PartialEq, Eq, Debug)]
106pub enum ParseSocketAddrNodeError {
107 ParseSocketDomainError(ParseSocketDomainError),
111}
112
113impl fmt::Display for ParseSocketAddrNodeError {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 match self {
116 Self::ParseSocketDomainError(err) => err.fmt(f),
117 }
118 }
119}
120
121impl std::error::Error for ParseSocketAddrNodeError {}
122
123impl From<ParseSocketDomainError> for ParseSocketAddrNodeError {
124 fn from(err: ParseSocketDomainError) -> Self {
125 Self::ParseSocketDomainError(err)
126 }
127}
128
129impl FromStr for SocketAddrNode {
130 type Err = ParseSocketAddrNodeError;
131
132 fn from_str(s: &str) -> Result<Self, Self::Err> {
133 if let Ok(addr) = s.parse::<SocketAddrExt>() {
134 return Ok(Self::AddrExt(addr));
135 }
136 Ok(Self::Domain(s.parse::<SocketDomain>()?))
137 }
138}
139
140#[test]
141fn test_socket_addr_node_from_str() {
142 use koibumi_net::domain::Domain;
143
144 let test = "example.org:1234".parse::<SocketAddrNode>().unwrap();
145 let expected = SocketAddrNode::Domain(SocketDomain::new(
146 Domain::new("example.org").unwrap(),
147 1234.into(),
148 ));
149 assert_eq!(test, expected);
150}
151
152impl From<SocketAddrNode> for SocksSocketAddr {
153 fn from(addr: SocketAddrNode) -> Self {
154 match addr {
155 SocketAddrNode::AddrExt(addr) => addr.into(),
156 SocketAddrNode::Domain(domain) => domain.into(),
157 }
158 }
159}