avalanche_types/codec/serde/
ip_port.rs1use std::net::{IpAddr, SocketAddr};
2
3use serde::{self, Deserialize, Deserializer, Serializer};
4use serde_with::{DeserializeAs, SerializeAs};
5use url::Url;
6
7pub fn serialize<S>(x: &SocketAddr, serializer: S) -> Result<S::Ok, S::Error>
9where
10 S: Serializer,
11{
12 serializer.serialize_str(&x.to_string())
14}
15
16pub fn deserialize<'de, D>(deserializer: D) -> Result<SocketAddr, D::Error>
18where
19 D: Deserializer<'de>,
20{
21 let s = String::deserialize(deserializer)?;
22
23 match s.parse() {
24 Ok(addr) => Ok(addr),
25 Err(e) => {
26 log::warn!("fallback to URL parsing {:?}", e);
27 let url = Url::parse(&s).map_err(serde::de::Error::custom)?;
28
29 let host = if let Some(hs) = url.host_str() {
30 hs.to_string()
31 } else {
32 return Err(serde::de::Error::custom("no host found"));
33 };
34 let ip: IpAddr = host.parse().map_err(serde::de::Error::custom)?;
35 let port = if let Some(port) = url.port() {
36 port
37 } else {
38 0 };
40 Ok(SocketAddr::new(ip, port))
41 }
42 }
43}
44
45pub struct IpPort(SocketAddr);
46
47impl SerializeAs<SocketAddr> for IpPort {
48 fn serialize_as<S>(x: &SocketAddr, serializer: S) -> Result<S::Ok, S::Error>
49 where
50 S: Serializer,
51 {
52 serializer.serialize_str(&x.to_string())
53 }
54}
55
56impl<'de> DeserializeAs<'de, SocketAddr> for IpPort {
57 fn deserialize_as<D>(deserializer: D) -> Result<SocketAddr, D::Error>
58 where
59 D: Deserializer<'de>,
60 {
61 let s = String::deserialize(deserializer)?;
62
63 match s.parse() {
64 Ok(addr) => Ok(addr),
65 Err(e) => {
66 log::warn!("fallback to URL parsing {:?}", e);
67 let url = Url::parse(&s).map_err(serde::de::Error::custom)?;
68
69 let host = if let Some(hs) = url.host_str() {
70 hs.to_string()
71 } else {
72 return Err(serde::de::Error::custom("no host found"));
73 };
74 let ip: IpAddr = host.parse().map_err(serde::de::Error::custom)?;
75 let port = if let Some(port) = url.port() {
76 port
77 } else {
78 0 };
80 Ok(SocketAddr::new(ip, port))
81 }
82 }
83 }
84}
85
86#[test]
88fn test_custom_de_serializer() {
89 use std::net::Ipv4Addr;
90
91 use serde::Serialize;
92 use serde_with::serde_as;
93
94 #[serde_as]
95 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
96 struct Data {
97 #[serde_as(as = "Vec<IpPort>")]
98 data: Vec<SocketAddr>,
99 }
100
101 let d = Data {
102 data: vec![
103 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(206, 189, 137, 87)), 9651),
104 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(158, 255, 67, 151)), 9651),
105 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(34, 216, 139, 126)), 9650),
106 ],
107 };
108
109 let yaml_encoded = serde_yaml::to_string(&d).unwrap();
110 println!("yaml_encoded:\n{}", yaml_encoded);
111 let yaml_decoded = serde_yaml::from_str(&yaml_encoded).unwrap();
112 assert_eq!(d, yaml_decoded);
113
114 let json_encoded = serde_json::to_string(&d).unwrap();
115 println!("json_encoded:\n{}", json_encoded);
116 let json_decoded = serde_json::from_str(&json_encoded).unwrap();
117 assert_eq!(d, json_decoded);
118
119 let json_decoded_2: Data = serde_json::from_str(
120 "
121
122{
123\"data\":[\"206.189.137.87:9651\", \"158.255.67.151:9651\", \"http://34.216.139.126:9650\"]
124}
125
126",
127 )
128 .unwrap();
129 assert_eq!(d, json_decoded_2);
130}