#![cfg(feature = "serde")]
use core::{
fmt,
net::{
IpAddr,
Ipv4Addr,
Ipv6Addr,
},
};
use serde::{
de,
ser,
};
pub fn serialize_any<S>(
serializer: S,
name: &'static str,
data: Option<(IpAddr, u8)>,
) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
match data {
None => {
let tag: u8 = 0xff;
let value = (tag, ());
serializer.serialize_newtype_struct(name, &value)
},
Some((IpAddr::V4(addr), len)) => {
assert!(len <= 32, "network length out of bounds for IPv4: {}", len);
let tag: u8 = len;
let value = (tag, addr);
serializer.serialize_newtype_struct(name, &value)
},
Some((IpAddr::V6(addr), len)) => {
assert!(len <= 128, "network length out of bounds for IPv4: {}", len);
let tag: u8 = len + 64;
let value = (tag, addr);
serializer.serialize_newtype_struct(name, &value)
},
}
}
pub fn serialize<S>(
serializer: S,
name: &'static str,
data: (IpAddr, u8),
) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serialize_any(serializer, name, Some(data))
}
pub fn serialize_v4<S>(
serializer: S,
name: &'static str,
data: (Ipv4Addr, u8),
) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serialize_any(serializer, name, Some((IpAddr::V4(data.0), data.1)))
}
pub fn serialize_v6<S>(
serializer: S,
name: &'static str,
data: (Ipv6Addr, u8),
) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serialize_any(serializer, name, Some((IpAddr::V6(data.0), data.1)))
}
pub fn deserialize_any<'de, D>(
deserializer: D,
name: &'static str,
) -> Result<Option<(IpAddr, u8)>, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Option<(IpAddr, u8)>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a tuple with two fields")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
let tag: u8 = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
match tag {
0xff => {
let _data: () = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
Ok(None)
},
0x00..=0x20 => {
let network_length = tag;
let addr: Ipv4Addr = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
Ok(Some((IpAddr::V4(addr), network_length)))
},
0x40..=0xc0 => {
let network_length = tag - 0x40;
let addr: Ipv6Addr = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
Ok(Some((IpAddr::V6(addr), network_length)))
},
_ => Err(de::Error::custom("invalid tag")),
}
}
}
struct NewTypeVisitor(&'static str);
impl<'de> de::Visitor<'de> for NewTypeVisitor {
type Value = Option<(IpAddr, u8)>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("newtype `")?;
formatter.write_str(self.0)?;
formatter.write_str("`")
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer.deserialize_tuple(2, Visitor)
}
}
deserializer.deserialize_newtype_struct(name, NewTypeVisitor(name))
}
pub fn deserialize<'de, D>(deserializer: D, name: &'static str) -> Result<(IpAddr, u8), D::Error>
where
D: de::Deserializer<'de>,
{
deserialize_any(deserializer, name)?.ok_or_else(|| de::Error::custom("invalid value: `any`"))
}
pub fn deserialize_v4<'de, D>(
deserializer: D,
name: &'static str,
) -> Result<(Ipv4Addr, u8), D::Error>
where
D: de::Deserializer<'de>,
{
match deserialize(deserializer, name)? {
(IpAddr::V4(addr), len) => Ok((addr, len)),
(IpAddr::V6(_), _) => Err(de::Error::custom("invalid type: `Ipv6Addr`")),
}
}
pub fn deserialize_v6<'de, D>(
deserializer: D,
name: &'static str,
) -> Result<(Ipv6Addr, u8), D::Error>
where
D: de::Deserializer<'de>,
{
match deserialize(deserializer, name)? {
(IpAddr::V4(_), _) => Err(de::Error::custom("invalid type: `Ipv4Addr`")),
(IpAddr::V6(addr), len) => Ok((addr, len)),
}
}
pub fn deserialize_parse<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: de::Deserializer<'de>,
T: core::str::FromStr,
T::Err: core::fmt::Display,
{
struct Visitor<T: core::str::FromStr>(core::marker::PhantomData<T>);
impl<'de, T> de::Visitor<'de> for Visitor<T>
where
T: core::str::FromStr,
T::Err: core::fmt::Display,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
v.parse::<T>().map_err(de::Error::custom)
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: de::Error,
{
match core::str::from_utf8(v) {
Ok(s) => self.visit_str(s),
Err(_) => Err(de::Error::invalid_value(de::Unexpected::Bytes(v), &self)),
}
}
}
deserializer.deserialize_str(Visitor::<T>(core::marker::PhantomData))
}