pub mod serde_ipaddr_option {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::net::IpAddr;
pub fn serialize<S>(ip: &Option<IpAddr>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(ip) = ip {
(1u8, ip.to_string()).serialize(serializer)
} else {
(0u8, "".to_string()).serialize(serializer)
}
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<IpAddr>, D::Error>
where
D: Deserializer<'de>,
{
let (flag, ip_str): (u8, String) = Deserialize::deserialize(deserializer)?;
match flag {
1 => ip_str.parse().map(Some).map_err(serde::de::Error::custom),
_ => Ok(None),
}
}
}
pub mod serde_ipaddr_vec {
use serde::{Deserialize, Deserializer, Serializer};
use std::net::IpAddr;
pub fn serialize<S>(ips: &Vec<IpAddr>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let ip_strings: Vec<String> = ips.iter().map(|ip| ip.to_string()).collect();
serializer.serialize_str(&ip_strings.join(","))
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<IpAddr>, D::Error>
where
D: Deserializer<'de>,
{
let ip_string = String::deserialize(deserializer)?;
let ips: Vec<IpAddr> = ip_string
.split(',')
.filter_map(|s| s.parse().ok())
.collect();
Ok(ips)
}
}
#[cfg(test)]
mod tests {
use super::{serde_ipaddr_option, serde_ipaddr_vec};
use bincode;
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct TestOptionIpAddr {
#[serde(with = "serde_ipaddr_option")]
ip: Option<IpAddr>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct TestVecIpAddr {
#[serde(with = "serde_ipaddr_vec")]
ips: Vec<IpAddr>,
}
#[test]
fn test_serde_ipaddr_option_serialize() {
let data = TestOptionIpAddr {
ip: Some("192.168.1.1".parse().unwrap()),
};
let serialized = bincode::serialize(&data).unwrap();
let deserialized: TestOptionIpAddr = bincode::deserialize(&serialized).unwrap();
assert_eq!(deserialized, data);
}
#[test]
fn test_serde_ipaddr_option_serialize_none() {
let data = TestOptionIpAddr { ip: None };
let serialized = bincode::serialize(&data).unwrap();
let deserialized: TestOptionIpAddr = bincode::deserialize(&serialized).unwrap();
assert_eq!(deserialized, data);
}
#[test]
fn test_serde_ipaddr_vec_serialize() {
let data = TestVecIpAddr {
ips: vec!["192.168.1.1".parse().unwrap(), "10.0.0.1".parse().unwrap()],
};
let serialized = bincode::serialize(&data).unwrap();
let deserialized: TestVecIpAddr = bincode::deserialize(&serialized).unwrap();
assert_eq!(deserialized, data);
}
#[test]
fn test_serde_ipaddr_vec_serialize_empty() {
let data = TestVecIpAddr { ips: vec![] };
let serialized = bincode::serialize(&data).unwrap();
let deserialized: TestVecIpAddr = bincode::deserialize(&serialized).unwrap();
assert_eq!(deserialized, data);
}
}