Skip to content

Instantly share code, notes, and snippets.

@RReverser RReverser/serde-cidr.rs
Last active Jan 17, 2018

Embed
What would you like to do?
pub struct IpCidr(::cidr::IpCidr);
impl Debug for IpCidr {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl Deref for IpCidr {
type Target = ::cidr::IpCidr;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Serialize, Deserialize)]
struct IpCidrRepr<'a> {
#[serde(borrow)]
#[serde(with = "::serde_bytes")]
address: Cow<'a, [u8]>,
network_length: u8,
}
impl Serialize for IpCidr {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
if ser.is_human_readable() {
return self.to_string().serialize(ser);
}
match self.0 {
::cidr::IpCidr::V4(ref cidr) => IpCidrRepr {
address: Cow::Borrowed(&cidr.first_address().octets()),
network_length: cidr.network_length(),
}.serialize(ser),
::cidr::IpCidr::V6(ref cidr) => IpCidrRepr {
address: Cow::Borrowed(&cidr.first_address().octets()),
network_length: cidr.network_length(),
}.serialize(ser),
}
}
}
impl<'de> Deserialize<'de> for IpCidr {
fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
if de.is_human_readable() {
let s: &str = Deserialize::deserialize(de)?;
return match s.parse() {
Ok(cidr) => Ok(IpCidr(cidr)),
Err(err) => Err(D::Error::custom(err)),
};
}
let repr = IpCidrRepr::deserialize(de)?;
let addr = match repr.address.len() {
4 => IpAddr::V4(Ipv4Addr::from(unsafe {
*(repr.address.as_ptr() as *const [u8; 4])
})),
16 => IpAddr::V6(Ipv6Addr::from(unsafe {
*(repr.address.as_ptr() as *const [u8; 16])
})),
_ => {
return Err(D::Error::invalid_length(
repr.address.len(),
&"4 for IPv4 or 16 for IPv16",
))
}
};
match ::cidr::IpCidr::new(addr, repr.network_length) {
Ok(cidr) => Ok(IpCidr(cidr)),
Err(err) => Err(D::Error::custom(err)),
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.