Last active
January 17, 2018 17:14
-
-
Save RReverser/757de5012cc01016abc4f9f4e69cc74b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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