aboutsummaryrefslogtreecommitdiff
path: root/src/ip.rs
diff options
context:
space:
mode:
authorHristo Venev <hristo@venev.name>2019-04-02 15:56:06 +0300
committerHristo Venev <hristo@venev.name>2019-04-02 15:57:45 +0300
commitb06338ec1d282a762440ad72c935717e404badca (patch)
treef6e441e97f7676e1acab6fc4ba72c3b875e97d9b /src/ip.rs
parentc3269142f8d6c016ce8100b86fcae2031b145a9a (diff)
Reorg, sources have names.
Diffstat (limited to 'src/ip.rs')
-rw-r--r--src/ip.rs344
1 files changed, 0 insertions, 344 deletions
diff --git a/src/ip.rs b/src/ip.rs
deleted file mode 100644
index d2ad17e..0000000
--- a/src/ip.rs
+++ /dev/null
@@ -1,344 +0,0 @@
-// Copyright 2019 Hristo Venev
-//
-// See COPYING.
-
-use serde;
-use std::iter::{FromIterator, IntoIterator};
-pub use std::net::{Ipv4Addr, Ipv6Addr};
-use std::str::FromStr;
-use std::{error, fmt, iter};
-
-#[derive(Debug)]
-pub struct NetParseError;
-
-impl error::Error for NetParseError {}
-impl fmt::Display for NetParseError {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "Invalid address")
- }
-}
-
-macro_rules! per_proto {
- ($nett:ident ($addrt:ident; $expecting:expr); $intt:ident($bytes:expr); $sett:ident) => {
- #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
- pub struct $nett {
- pub address: $addrt,
- pub prefix_len: u8,
- }
-
- impl $nett {
- const BITS: u8 = $bytes * 8;
-
- pub fn contains(&self, other: &$nett) -> bool {
- if self.prefix_len > other.prefix_len {
- return false;
- }
- if self.prefix_len == other.prefix_len {
- return self.address == other.address;
- }
- if self.prefix_len == 0 {
- return true;
- }
- // self.prefix_len < other.prefix_len = BITS
- let shift = Self::BITS - self.prefix_len;
- let v1: $intt = self.address.into();
- let v2: $intt = other.address.into();
- v1 >> shift == v2 >> shift
- }
- }
-
- impl fmt::Display for $nett {
- #[inline]
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}/{}", self.address, self.prefix_len)
- }
- }
-
- impl FromStr for $nett {
- type Err = NetParseError;
- fn from_str(s: &str) -> Result<$nett, NetParseError> {
- let (addr, pfx) = pfx_split(s)?;
- let addr = $addrt::from_str(addr).map_err(|_| NetParseError)?;
-
- let r = $nett {
- address: addr,
- prefix_len: pfx,
- };
- if !r.is_valid() {
- return Err(NetParseError);
- }
- Ok(r)
- }
- }
-
- impl serde::Serialize for $nett {
- fn serialize<S: serde::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
- if ser.is_human_readable() {
- ser.collect_str(self)
- } else {
- let mut buf = [0u8; $bytes + 1];
- *array_mut_ref![&mut buf, 0, $bytes] = self.address.octets();
- buf[$bytes] = self.prefix_len;
- ser.serialize_bytes(&buf)
- }
- }
- }
-
- impl<'de> serde::Deserialize<'de> for $nett {
- fn deserialize<D: serde::Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
- if de.is_human_readable() {
- struct NetVisitor;
- impl<'de> serde::de::Visitor<'de> for NetVisitor {
- type Value = $nett;
-
- #[inline]
- fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str($expecting)
- }
-
- #[inline]
- fn visit_str<E: serde::de::Error>(self, s: &str) -> Result<Self::Value, E> {
- s.parse().map_err(E::custom)
- }
- }
- de.deserialize_str(NetVisitor)
- } else {
- let buf = <[u8; $bytes + 1] as serde::Deserialize>::deserialize(de)?;
- let r = $nett {
- address: (*array_ref![&buf, 0, $bytes]).into(),
- prefix_len: buf[$bytes],
- };
- if r.is_valid() {
- return Err(serde::de::Error::custom(NetParseError));
- }
- Ok(r)
- }
- }
- }
-
- #[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
- pub struct $sett {
- nets: Vec<$nett>,
- }
-
- impl Default for $sett {
- #[inline]
- fn default() -> Self {
- $sett::new()
- }
- }
-
- impl $sett {
- #[inline]
- pub fn new() -> Self {
- $sett { nets: vec![] }
- }
-
- #[inline]
- fn siblings(a: &$nett, b: &$nett) -> bool {
- let pfx = a.prefix_len;
- if b.prefix_len != pfx || pfx == 0 {
- return false;
- }
- let a: $intt = a.address.into();
- let b: $intt = b.address.into();
- a ^ b == 1 << ($nett::BITS - pfx)
- }
-
- pub fn insert(&mut self, mut net: $nett) {
- let mut i = match self.nets.binary_search(&net) {
- Err(i) => i,
- Ok(_) => {
- return;
- }
- };
- let mut j = i;
- if i != 0 && self.nets[i - 1].contains(&net) {
- net = self.nets[i - 1];
- i -= 1;
- }
- while j < self.nets.len() && net.contains(&self.nets[j]) {
- j += 1;
- }
- loop {
- if j < self.nets.len() && Self::siblings(&net, &self.nets[j]) {
- j += 1;
- } else if i != 0 && Self::siblings(&self.nets[i - 1], &net) {
- net = self.nets[i - 1];
- i -= 1;
- } else {
- break;
- }
- net.prefix_len -= 1;
- }
- self.nets.splice(i..j, iter::once(net));
- }
-
- pub fn contains(&self, net: &$nett) -> bool {
- match self.nets.binary_search(&net) {
- Err(i) => {
- if i == 0 {
- return false;
- }
- self.nets[i - 1].contains(&net)
- }
- Ok(_) => true,
- }
- }
-
- #[inline]
- pub fn iter(&self) -> std::slice::Iter<$nett> {
- self.nets.iter()
- }
- }
-
- impl IntoIterator for $sett {
- type Item = $nett;
- type IntoIter = std::vec::IntoIter<$nett>;
-
- #[inline]
- fn into_iter(self) -> Self::IntoIter {
- self.nets.into_iter()
- }
- }
-
- impl FromIterator<$nett> for $sett {
- #[inline]
- fn from_iter<I: IntoIterator<Item = $nett>>(it: I) -> $sett {
- let mut r = $sett::new();
- for net in it {
- r.insert(net);
- }
- r
- }
- }
-
- impl<'a> From<$nett> for $sett {
- #[inline]
- fn from(v: $nett) -> $sett {
- $sett { nets: vec![v] }
- }
- }
-
- impl<'a> From<[$nett; 1]> for $sett {
- #[inline]
- fn from(v: [$nett; 1]) -> $sett {
- $sett { nets: vec![v[0]] }
- }
- }
-
- impl From<$sett> for Vec<$nett> {
- fn from(v: $sett) -> Vec<$nett> {
- v.nets
- }
- }
-
- impl From<Vec<$nett>> for $sett {
- fn from(nets: Vec<$nett>) -> $sett {
- let mut s = $sett { nets };
- let len = s.nets.len();
- if len == 0 {
- return s;
- }
- s.nets.sort();
- let mut i = 1;
- for j in 1..len {
- let mut net = s.nets[j];
- if s.nets[i - 1].contains(&net) {
- net = s.nets[i - 1];
- i -= 1;
- }
- while i != 0 && Self::siblings(&s.nets[i - 1], &net) {
- net = s.nets[i - 1];
- net.prefix_len -= 1;
- i -= 1;
- }
- s.nets[i] = net;
- i += 1;
- }
- s.nets.splice(i.., iter::empty());
- s
- }
- }
-
- impl<'a> From<&'a [$nett]> for $sett {
- #[inline]
- fn from(nets: &'a [$nett]) -> $sett {
- Vec::from(nets).into()
- }
- }
-
- impl<'a> From<&'a mut [$nett]> for $sett {
- #[inline]
- fn from(nets: &'a mut [$nett]) -> $sett {
- Vec::from(nets).into()
- }
- }
-
- impl serde::Serialize for $sett {
- #[inline]
- fn serialize<S: serde::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
- <Vec<$nett> as serde::Serialize>::serialize(&self.nets, ser)
- }
- }
-
- impl<'de> serde::Deserialize<'de> for $sett {
- #[inline]
- fn deserialize<D: serde::Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
- <Vec<$nett> as serde::Deserialize>::deserialize(de).map($sett::from)
- }
- }
- };
-}
-
-per_proto!(Ipv4Net(Ipv4Addr; "IPv4 network"); u32(4); Ipv4Set);
-per_proto!(Ipv6Net(Ipv6Addr; "IPv6 network"); u128(16); Ipv6Set);
-
-impl Ipv4Net {
- pub fn is_valid(&self) -> bool {
- let pfx = self.prefix_len;
- if pfx > 32 {
- return false;
- }
- if pfx == 32 {
- return true;
- }
- let val: u32 = self.address.into();
- val & (u32::max_value() >> pfx) == 0
- }
-}
-
-impl Ipv6Net {
- pub fn is_valid(&self) -> bool {
- let pfx = self.prefix_len;
- if pfx > 128 {
- return false;
- }
- if pfx == 128 {
- return true;
- }
-
- let val: u128 = self.address.into();
- let val: [u64; 2] = [(val >> 64) as u64, val as u64];
- if pfx >= 64 {
- return val[1] & (u64::max_value() >> (pfx - 64)) == 0;
- }
- if val[1] != 0 {
- return false;
- }
- val[0] & (u64::max_value() >> pfx) == 0
- }
-}
-
-fn pfx_split(s: &str) -> Result<(&str, u8), NetParseError> {
- let i = match s.find('/') {
- Some(i) => i,
- None => {
- return Err(NetParseError);
- }
- };
- let (addr, pfx) = s.split_at(i);
- let pfx = u8::from_str(&pfx[1..]).map_err(|_| NetParseError)?;
- Ok((addr, pfx))
-}