RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
966
zeroidc/vendor/ipnet/src/ipext.rs
vendored
Normal file
966
zeroidc/vendor/ipnet/src/ipext.rs
vendored
Normal file
@@ -0,0 +1,966 @@
|
||||
//! Extensions to the standard IP address types for common operations.
|
||||
//!
|
||||
//! The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
|
||||
//! the `Ipv4Addr` and `Ipv6Addr` types with methods to perform these
|
||||
//! operations.
|
||||
|
||||
use std::cmp::Ordering::{Less, Equal};
|
||||
use std::iter::{FusedIterator, DoubleEndedIterator};
|
||||
use std::mem;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
|
||||
/// Provides a `saturating_add()` method for `Ipv4Addr` and `Ipv6Addr`.
|
||||
///
|
||||
/// Adding an integer to an IP address returns the modified IP address.
|
||||
/// A `u32` may added to an IPv4 address and a `u128` may be added to
|
||||
/// an IPv6 address.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
/// use ipnet::IpAdd;
|
||||
///
|
||||
/// let ip0: Ipv4Addr = "192.168.0.0".parse().unwrap();
|
||||
/// let ip1: Ipv4Addr = "192.168.0.5".parse().unwrap();
|
||||
/// let ip2: Ipv4Addr = "255.255.255.254".parse().unwrap();
|
||||
/// let max: Ipv4Addr = "255.255.255.255".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(ip0.saturating_add(5), ip1);
|
||||
/// assert_eq!(ip2.saturating_add(1), max);
|
||||
/// assert_eq!(ip2.saturating_add(5), max);
|
||||
///
|
||||
/// let ip0: Ipv6Addr = "fd00::".parse().unwrap();
|
||||
/// let ip1: Ipv6Addr = "fd00::5".parse().unwrap();
|
||||
/// let ip2: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe".parse().unwrap();
|
||||
/// let max: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(ip0.saturating_add(5), ip1);
|
||||
/// assert_eq!(ip2.saturating_add(1), max);
|
||||
/// assert_eq!(ip2.saturating_add(5), max);
|
||||
/// ```
|
||||
pub trait IpAdd<RHS = Self> {
|
||||
type Output;
|
||||
fn saturating_add(self, rhs: RHS) -> Self::Output;
|
||||
}
|
||||
|
||||
/// Provides a `saturating_sub()` method for `Ipv4Addr` and `Ipv6Addr`.
|
||||
///
|
||||
/// Subtracting an integer from an IP address returns the modified IP
|
||||
/// address. A `u32` may be subtracted from an IPv4 address and a `u128`
|
||||
/// may be subtracted from an IPv6 address.
|
||||
///
|
||||
/// Subtracting an IP address from another IP address of the same type
|
||||
/// returns an integer of the appropriate width. A `u32` for IPv4 and a
|
||||
/// `u128` for IPv6. Subtracting IP addresses is useful for getting
|
||||
/// the range between two IP addresses.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
/// use ipnet::IpSub;
|
||||
///
|
||||
/// let min: Ipv4Addr = "0.0.0.0".parse().unwrap();
|
||||
/// let ip1: Ipv4Addr = "192.168.1.5".parse().unwrap();
|
||||
/// let ip2: Ipv4Addr = "192.168.1.100".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(min.saturating_sub(ip1), 0);
|
||||
/// assert_eq!(ip2.saturating_sub(ip1), 95);
|
||||
/// assert_eq!(min.saturating_sub(5), min);
|
||||
/// assert_eq!(ip2.saturating_sub(95), ip1);
|
||||
///
|
||||
/// let min: Ipv6Addr = "::".parse().unwrap();
|
||||
/// let ip1: Ipv6Addr = "fd00::5".parse().unwrap();
|
||||
/// let ip2: Ipv6Addr = "fd00::64".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(min.saturating_sub(ip1), 0);
|
||||
/// assert_eq!(ip2.saturating_sub(ip1), 95);
|
||||
/// assert_eq!(min.saturating_sub(5u128), min);
|
||||
/// assert_eq!(ip2.saturating_sub(95u128), ip1);
|
||||
/// ```
|
||||
pub trait IpSub<RHS = Self> {
|
||||
type Output;
|
||||
fn saturating_sub(self, rhs: RHS) -> Self::Output;
|
||||
}
|
||||
|
||||
/// Provides a `bitand()` method for `Ipv4Addr` and `Ipv6Addr`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
/// use ipnet::IpBitAnd;
|
||||
///
|
||||
/// let ip: Ipv4Addr = "192.168.1.1".parse().unwrap();
|
||||
/// let mask: Ipv4Addr = "255.255.0.0".parse().unwrap();
|
||||
/// let res: Ipv4Addr = "192.168.0.0".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(ip.bitand(mask), res);
|
||||
/// assert_eq!(ip.bitand(0xffff0000), res);
|
||||
///
|
||||
/// let ip: Ipv6Addr = "fd00:1234::1".parse().unwrap();
|
||||
/// let mask: Ipv6Addr = "ffff::".parse().unwrap();
|
||||
/// let res: Ipv6Addr = "fd00::".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(ip.bitand(mask), res);
|
||||
/// assert_eq!(ip.bitand(0xffff_0000_0000_0000_0000_0000_0000_0000u128), res);
|
||||
/// ```
|
||||
pub trait IpBitAnd<RHS = Self> {
|
||||
type Output;
|
||||
fn bitand(self, rhs: RHS) -> Self::Output;
|
||||
}
|
||||
|
||||
/// Provides a `bitor()` method for `Ipv4Addr` and `Ipv6Addr`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
/// use ipnet::IpBitOr;
|
||||
///
|
||||
/// let ip: Ipv4Addr = "10.1.1.1".parse().unwrap();
|
||||
/// let mask: Ipv4Addr = "0.0.0.255".parse().unwrap();
|
||||
/// let res: Ipv4Addr = "10.1.1.255".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(ip.bitor(mask), res);
|
||||
/// assert_eq!(ip.bitor(0x000000ff), res);
|
||||
///
|
||||
/// let ip: Ipv6Addr = "fd00::1".parse().unwrap();
|
||||
/// let mask: Ipv6Addr = "::ffff:ffff".parse().unwrap();
|
||||
/// let res: Ipv6Addr = "fd00::ffff:ffff".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(ip.bitor(mask), res);
|
||||
/// assert_eq!(ip.bitor(u128::from(0xffffffffu32)), res);
|
||||
/// ```
|
||||
pub trait IpBitOr<RHS = Self> {
|
||||
type Output;
|
||||
fn bitor(self, rhs: RHS) -> Self::Output;
|
||||
}
|
||||
|
||||
macro_rules! ip_add_impl {
|
||||
($lhs:ty, $rhs:ty, $output:ty, $inner:ty) => (
|
||||
impl IpAdd<$rhs> for $lhs {
|
||||
type Output = $output;
|
||||
|
||||
fn saturating_add(self, rhs: $rhs) -> $output {
|
||||
let lhs: $inner = self.into();
|
||||
let rhs: $inner = rhs.into();
|
||||
(lhs.saturating_add(rhs.into())).into()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! ip_sub_impl {
|
||||
($lhs:ty, $rhs:ty, $output:ty, $inner:ty) => (
|
||||
impl IpSub<$rhs> for $lhs {
|
||||
type Output = $output;
|
||||
|
||||
fn saturating_sub(self, rhs: $rhs) -> $output {
|
||||
let lhs: $inner = self.into();
|
||||
let rhs: $inner = rhs.into();
|
||||
(lhs.saturating_sub(rhs.into())).into()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ip_add_impl!(Ipv4Addr, u32, Ipv4Addr, u32);
|
||||
ip_add_impl!(Ipv6Addr, u128, Ipv6Addr, u128);
|
||||
|
||||
ip_sub_impl!(Ipv4Addr, Ipv4Addr, u32, u32);
|
||||
ip_sub_impl!(Ipv4Addr, u32, Ipv4Addr, u32);
|
||||
ip_sub_impl!(Ipv6Addr, Ipv6Addr, u128, u128);
|
||||
ip_sub_impl!(Ipv6Addr, u128, Ipv6Addr, u128);
|
||||
|
||||
macro_rules! ip_bitops_impl {
|
||||
($(($lhs:ty, $rhs:ty, $t:ty),)*) => {
|
||||
$(
|
||||
impl IpBitAnd<$rhs> for $lhs {
|
||||
type Output = $lhs;
|
||||
|
||||
fn bitand(self, rhs: $rhs) -> $lhs {
|
||||
let lhs: $t = self.into();
|
||||
let rhs: $t = rhs.into();
|
||||
(lhs & rhs).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl IpBitOr<$rhs> for $lhs {
|
||||
type Output = $lhs;
|
||||
|
||||
fn bitor(self, rhs: $rhs) -> $lhs {
|
||||
let lhs: $t = self.into();
|
||||
let rhs: $t = rhs.into();
|
||||
(lhs | rhs).into()
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
ip_bitops_impl! {
|
||||
(Ipv4Addr, Ipv4Addr, u32),
|
||||
(Ipv4Addr, u32, u32),
|
||||
(Ipv6Addr, Ipv6Addr, u128),
|
||||
(Ipv6Addr, u128, u128),
|
||||
}
|
||||
|
||||
// A barebones copy of the current unstable Step trait used by the
|
||||
// IpAddrRange, Ipv4AddrRange, and Ipv6AddrRange types below, and the
|
||||
// Subnets types in ipnet.
|
||||
pub trait IpStep {
|
||||
fn replace_one(&mut self) -> Self;
|
||||
fn replace_zero(&mut self) -> Self;
|
||||
fn add_one(&self) -> Self;
|
||||
fn sub_one(&self) -> Self;
|
||||
}
|
||||
|
||||
impl IpStep for Ipv4Addr {
|
||||
fn replace_one(&mut self) -> Self {
|
||||
mem::replace(self, Ipv4Addr::new(0, 0, 0, 1))
|
||||
}
|
||||
fn replace_zero(&mut self) -> Self {
|
||||
mem::replace(self, Ipv4Addr::new(0, 0, 0, 0))
|
||||
}
|
||||
fn add_one(&self) -> Self {
|
||||
self.saturating_add(1)
|
||||
}
|
||||
fn sub_one(&self) -> Self {
|
||||
self.saturating_sub(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl IpStep for Ipv6Addr {
|
||||
fn replace_one(&mut self) -> Self {
|
||||
mem::replace(self, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1))
|
||||
}
|
||||
fn replace_zero(&mut self) -> Self {
|
||||
mem::replace(self, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0))
|
||||
}
|
||||
fn add_one(&self) -> Self {
|
||||
self.saturating_add(1)
|
||||
}
|
||||
fn sub_one(&self) -> Self {
|
||||
self.saturating_sub(1)
|
||||
}
|
||||
}
|
||||
|
||||
/// An `Iterator` over a range of IP addresses, either IPv4 or IPv6.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::IpAddr;
|
||||
/// use ipnet::{IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
|
||||
///
|
||||
/// let hosts = IpAddrRange::from(Ipv4AddrRange::new(
|
||||
/// "10.0.0.0".parse().unwrap(),
|
||||
/// "10.0.0.3".parse().unwrap(),
|
||||
/// ));
|
||||
///
|
||||
/// assert_eq!(hosts.collect::<Vec<IpAddr>>(), vec![
|
||||
/// "10.0.0.0".parse::<IpAddr>().unwrap(),
|
||||
/// "10.0.0.1".parse().unwrap(),
|
||||
/// "10.0.0.2".parse().unwrap(),
|
||||
/// "10.0.0.3".parse().unwrap(),
|
||||
/// ]);
|
||||
///
|
||||
/// let hosts = IpAddrRange::from(Ipv6AddrRange::new(
|
||||
/// "fd00::".parse().unwrap(),
|
||||
/// "fd00::3".parse().unwrap(),
|
||||
/// ));
|
||||
///
|
||||
/// assert_eq!(hosts.collect::<Vec<IpAddr>>(), vec![
|
||||
/// "fd00::0".parse::<IpAddr>().unwrap(),
|
||||
/// "fd00::1".parse().unwrap(),
|
||||
/// "fd00::2".parse().unwrap(),
|
||||
/// "fd00::3".parse().unwrap(),
|
||||
/// ]);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
||||
pub enum IpAddrRange {
|
||||
V4(Ipv4AddrRange),
|
||||
V6(Ipv6AddrRange),
|
||||
}
|
||||
|
||||
/// An `Iterator` over a range of IPv4 addresses.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::Ipv4Addr;
|
||||
/// use ipnet::Ipv4AddrRange;
|
||||
///
|
||||
/// let hosts = Ipv4AddrRange::new(
|
||||
/// "10.0.0.0".parse().unwrap(),
|
||||
/// "10.0.0.3".parse().unwrap(),
|
||||
/// );
|
||||
///
|
||||
/// assert_eq!(hosts.collect::<Vec<Ipv4Addr>>(), vec![
|
||||
/// "10.0.0.0".parse::<Ipv4Addr>().unwrap(),
|
||||
/// "10.0.0.1".parse().unwrap(),
|
||||
/// "10.0.0.2".parse().unwrap(),
|
||||
/// "10.0.0.3".parse().unwrap(),
|
||||
/// ]);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
||||
pub struct Ipv4AddrRange {
|
||||
start: Ipv4Addr,
|
||||
end: Ipv4Addr,
|
||||
}
|
||||
|
||||
/// An `Iterator` over a range of IPv6 addresses.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::Ipv6Addr;
|
||||
/// use ipnet::Ipv6AddrRange;
|
||||
///
|
||||
/// let hosts = Ipv6AddrRange::new(
|
||||
/// "fd00::".parse().unwrap(),
|
||||
/// "fd00::3".parse().unwrap(),
|
||||
/// );
|
||||
///
|
||||
/// assert_eq!(hosts.collect::<Vec<Ipv6Addr>>(), vec![
|
||||
/// "fd00::".parse::<Ipv6Addr>().unwrap(),
|
||||
/// "fd00::1".parse().unwrap(),
|
||||
/// "fd00::2".parse().unwrap(),
|
||||
/// "fd00::3".parse().unwrap(),
|
||||
/// ]);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
||||
pub struct Ipv6AddrRange {
|
||||
start: Ipv6Addr,
|
||||
end: Ipv6Addr,
|
||||
}
|
||||
|
||||
impl From<Ipv4AddrRange> for IpAddrRange {
|
||||
fn from(i: Ipv4AddrRange) -> IpAddrRange {
|
||||
IpAddrRange::V4(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ipv6AddrRange> for IpAddrRange {
|
||||
fn from(i: Ipv6AddrRange) -> IpAddrRange {
|
||||
IpAddrRange::V6(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ipv4AddrRange {
|
||||
pub fn new(start: Ipv4Addr, end: Ipv4Addr) -> Self {
|
||||
Ipv4AddrRange {
|
||||
start: start,
|
||||
end: end,
|
||||
}
|
||||
}
|
||||
/// Counts the number of Ipv4Addr in this range.
|
||||
/// This method will never overflow or panic.
|
||||
fn count_u64(&self) -> u64 {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) => {
|
||||
let count: u32 = self.end.saturating_sub(self.start);
|
||||
let count = count as u64 + 1; // Never overflows
|
||||
count
|
||||
},
|
||||
Some(Equal) => 1,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ipv6AddrRange {
|
||||
pub fn new(start: Ipv6Addr, end: Ipv6Addr) -> Self {
|
||||
Ipv6AddrRange {
|
||||
start: start,
|
||||
end: end,
|
||||
}
|
||||
}
|
||||
/// Counts the number of Ipv6Addr in this range.
|
||||
/// This method may overflow or panic if start
|
||||
/// is 0 and end is u128::MAX
|
||||
fn count_u128(&self) -> u128 {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) => {
|
||||
let count = self.end.saturating_sub(self.start);
|
||||
// May overflow or panic
|
||||
count + 1
|
||||
},
|
||||
Some(Equal) => 1,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
/// True only if count_u128 does not overflow
|
||||
fn can_count_u128(&self) -> bool {
|
||||
self.start != Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)
|
||||
|| self.end != Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for IpAddrRange {
|
||||
type Item = IpAddr;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match *self {
|
||||
IpAddrRange::V4(ref mut a) => a.next().map(IpAddr::V4),
|
||||
IpAddrRange::V6(ref mut a) => a.next().map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
match self {
|
||||
IpAddrRange::V4(a) => a.count(),
|
||||
IpAddrRange::V6(a) => a.count(),
|
||||
}
|
||||
}
|
||||
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
match self {
|
||||
IpAddrRange::V4(a) => a.last().map(IpAddr::V4),
|
||||
IpAddrRange::V6(a) => a.last().map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
|
||||
fn max(self) -> Option<Self::Item> {
|
||||
match self {
|
||||
IpAddrRange::V4(a) => Iterator::max(a).map(IpAddr::V4),
|
||||
IpAddrRange::V6(a) => Iterator::max(a).map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
|
||||
fn min(self) -> Option<Self::Item> {
|
||||
match self {
|
||||
IpAddrRange::V4(a) => Iterator::min(a).map(IpAddr::V4),
|
||||
IpAddrRange::V6(a) => Iterator::min(a).map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
match *self {
|
||||
IpAddrRange::V4(ref mut a) => a.nth(n).map(IpAddr::V4),
|
||||
IpAddrRange::V6(ref mut a) => a.nth(n).map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match *self {
|
||||
IpAddrRange::V4(ref a) => a.size_hint(),
|
||||
IpAddrRange::V6(ref a) => a.size_hint(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Ipv4AddrRange {
|
||||
type Item = Ipv4Addr;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) => {
|
||||
let next = self.start.add_one();
|
||||
Some(mem::replace(&mut self.start, next))
|
||||
},
|
||||
Some(Equal) => {
|
||||
self.end.replace_zero();
|
||||
Some(self.start.replace_one())
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(const_err)]
|
||||
#[allow(arithmetic_overflow)]
|
||||
fn count(self) -> usize {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) => {
|
||||
// Adding one here might overflow u32.
|
||||
// Instead, wait until after converted to usize
|
||||
let count: u32 = self.end.saturating_sub(self.start);
|
||||
|
||||
// usize might only be 16 bits,
|
||||
// so need to explicitly check for overflow.
|
||||
// 'usize::MAX as u32' is okay here - if usize is 64 bits,
|
||||
// value truncates to u32::MAX
|
||||
if count <= std::usize::MAX as u32 {
|
||||
count as usize + 1
|
||||
// count overflows usize
|
||||
} else {
|
||||
// emulate standard overflow/panic behavior
|
||||
std::usize::MAX + 2 + count as usize
|
||||
}
|
||||
},
|
||||
Some(Equal) => 1,
|
||||
_ => 0
|
||||
}
|
||||
}
|
||||
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) | Some(Equal) => Some(self.end),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn max(self) -> Option<Self::Item> {
|
||||
self.last()
|
||||
}
|
||||
|
||||
fn min(self) -> Option<Self::Item> {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) | Some(Equal) => Some(self.start),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
let n = n as u64;
|
||||
let count = self.count_u64();
|
||||
if n >= count {
|
||||
self.end.replace_zero();
|
||||
self.start.replace_one();
|
||||
None
|
||||
} else if n == count - 1 {
|
||||
self.start.replace_one();
|
||||
Some(self.end.replace_zero())
|
||||
} else {
|
||||
let nth = self.start.saturating_add(n as u32);
|
||||
self.start = nth.add_one();
|
||||
Some(nth)
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let count = self.count_u64();
|
||||
if count > std::usize::MAX as u64 {
|
||||
(std::usize::MAX, None)
|
||||
} else {
|
||||
let count = count as usize;
|
||||
(count, Some(count))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Ipv6AddrRange {
|
||||
type Item = Ipv6Addr;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) => {
|
||||
let next = self.start.add_one();
|
||||
Some(mem::replace(&mut self.start, next))
|
||||
},
|
||||
Some(Equal) => {
|
||||
self.end.replace_zero();
|
||||
Some(self.start.replace_one())
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(const_err)]
|
||||
#[allow(arithmetic_overflow)]
|
||||
fn count(self) -> usize {
|
||||
let count = self.count_u128();
|
||||
// count fits in usize
|
||||
if count <= std::usize::MAX as u128 {
|
||||
count as usize
|
||||
// count does not fit in usize
|
||||
} else {
|
||||
// emulate standard overflow/panic behavior
|
||||
std::usize::MAX + 1 + count as usize
|
||||
}
|
||||
}
|
||||
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) | Some(Equal) => Some(self.end),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn max(self) -> Option<Self::Item> {
|
||||
self.last()
|
||||
}
|
||||
|
||||
fn min(self) -> Option<Self::Item> {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) | Some(Equal) => Some(self.start),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
let n = n as u128;
|
||||
if self.can_count_u128() {
|
||||
let count = self.count_u128();
|
||||
if n >= count {
|
||||
self.end.replace_zero();
|
||||
self.start.replace_one();
|
||||
None
|
||||
} else if n == count - 1 {
|
||||
self.start.replace_one();
|
||||
Some(self.end.replace_zero())
|
||||
} else {
|
||||
let nth = self.start.saturating_add(n);
|
||||
self.start = nth.add_one();
|
||||
Some(nth)
|
||||
}
|
||||
// count overflows u128; n is 64-bits at most.
|
||||
// therefore, n can never exceed count
|
||||
} else {
|
||||
let nth = self.start.saturating_add(n);
|
||||
self.start = nth.add_one();
|
||||
Some(nth)
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.can_count_u128() {
|
||||
let count = self.count_u128();
|
||||
if count > std::usize::MAX as u128 {
|
||||
(std::usize::MAX, None)
|
||||
} else {
|
||||
let count = count as usize;
|
||||
(count, Some(count))
|
||||
}
|
||||
} else {
|
||||
(std::usize::MAX, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for IpAddrRange {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
match *self {
|
||||
IpAddrRange::V4(ref mut a) => a.next_back().map(IpAddr::V4),
|
||||
IpAddrRange::V6(ref mut a) => a.next_back().map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
match *self {
|
||||
IpAddrRange::V4(ref mut a) => a.nth_back(n).map(IpAddr::V4),
|
||||
IpAddrRange::V6(ref mut a) => a.nth_back(n).map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Ipv4AddrRange {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) => {
|
||||
let next_back = self.end.sub_one();
|
||||
Some(mem::replace(&mut self.end, next_back))
|
||||
},
|
||||
Some(Equal) => {
|
||||
self.end.replace_zero();
|
||||
Some(self.start.replace_one())
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
let n = n as u64;
|
||||
let count = self.count_u64();
|
||||
if n >= count {
|
||||
self.end.replace_zero();
|
||||
self.start.replace_one();
|
||||
None
|
||||
} else if n == count - 1 {
|
||||
self.end.replace_zero();
|
||||
Some(self.start.replace_one())
|
||||
} else {
|
||||
let nth_back = self.end.saturating_sub(n as u32);
|
||||
self.end = nth_back.sub_one();
|
||||
Some(nth_back)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Ipv6AddrRange {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
match self.start.partial_cmp(&self.end) {
|
||||
Some(Less) => {
|
||||
let next_back = self.end.sub_one();
|
||||
Some(mem::replace(&mut self.end, next_back))
|
||||
},
|
||||
Some(Equal) => {
|
||||
self.end.replace_zero();
|
||||
Some(self.start.replace_one())
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
let n = n as u128;
|
||||
if self.can_count_u128() {
|
||||
let count = self.count_u128();
|
||||
if n >= count {
|
||||
self.end.replace_zero();
|
||||
self.start.replace_one();
|
||||
None
|
||||
}
|
||||
else if n == count - 1 {
|
||||
self.end.replace_zero();
|
||||
Some(self.start.replace_one())
|
||||
} else {
|
||||
let nth_back = self.end.saturating_sub(n);
|
||||
self.end = nth_back.sub_one();
|
||||
Some(nth_back)
|
||||
}
|
||||
// count overflows u128; n is 64-bits at most.
|
||||
// therefore, n can never exceed count
|
||||
} else {
|
||||
let nth_back = self.end.saturating_sub(n);
|
||||
self.end = nth_back.sub_one();
|
||||
Some(nth_back)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FusedIterator for IpAddrRange {}
|
||||
impl FusedIterator for Ipv4AddrRange {}
|
||||
impl FusedIterator for Ipv6AddrRange {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use std::str::FromStr;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_ipaddrrange() {
|
||||
// Next, Next-Back
|
||||
let i = Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("10.0.0.0").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.3").unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(i.collect::<Vec<Ipv4Addr>>(), vec![
|
||||
Ipv4Addr::from_str("10.0.0.0").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.1").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.2").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.3").unwrap(),
|
||||
]);
|
||||
|
||||
let mut v = i.collect::<Vec<_>>();
|
||||
v.reverse();
|
||||
assert_eq!(v, i.rev().collect::<Vec<_>>());
|
||||
|
||||
let i = Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("255.255.255.254").unwrap(),
|
||||
Ipv4Addr::from_str("255.255.255.255").unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(i.collect::<Vec<Ipv4Addr>>(), vec![
|
||||
Ipv4Addr::from_str("255.255.255.254").unwrap(),
|
||||
Ipv4Addr::from_str("255.255.255.255").unwrap(),
|
||||
]);
|
||||
|
||||
let i = Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("fd00::").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::3").unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(i.collect::<Vec<Ipv6Addr>>(), vec![
|
||||
Ipv6Addr::from_str("fd00::").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::1").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::2").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::3").unwrap(),
|
||||
]);
|
||||
|
||||
let mut v = i.collect::<Vec<_>>();
|
||||
v.reverse();
|
||||
assert_eq!(v, i.rev().collect::<Vec<_>>());
|
||||
|
||||
let i = Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe").unwrap(),
|
||||
Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(i.collect::<Vec<Ipv6Addr>>(), vec![
|
||||
Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe").unwrap(),
|
||||
Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(),
|
||||
]);
|
||||
|
||||
let i = IpAddrRange::from(Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("10.0.0.0").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.3").unwrap(),
|
||||
));
|
||||
|
||||
assert_eq!(i.collect::<Vec<IpAddr>>(), vec![
|
||||
IpAddr::from_str("10.0.0.0").unwrap(),
|
||||
IpAddr::from_str("10.0.0.1").unwrap(),
|
||||
IpAddr::from_str("10.0.0.2").unwrap(),
|
||||
IpAddr::from_str("10.0.0.3").unwrap(),
|
||||
]);
|
||||
|
||||
let mut v = i.collect::<Vec<_>>();
|
||||
v.reverse();
|
||||
assert_eq!(v, i.rev().collect::<Vec<_>>());
|
||||
|
||||
let i = IpAddrRange::from(Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("255.255.255.254").unwrap(),
|
||||
Ipv4Addr::from_str("255.255.255.255").unwrap()
|
||||
));
|
||||
|
||||
assert_eq!(i.collect::<Vec<IpAddr>>(), vec![
|
||||
IpAddr::from_str("255.255.255.254").unwrap(),
|
||||
IpAddr::from_str("255.255.255.255").unwrap(),
|
||||
]);
|
||||
|
||||
let i = IpAddrRange::from(Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("fd00::").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::3").unwrap(),
|
||||
));
|
||||
|
||||
assert_eq!(i.collect::<Vec<IpAddr>>(), vec![
|
||||
IpAddr::from_str("fd00::").unwrap(),
|
||||
IpAddr::from_str("fd00::1").unwrap(),
|
||||
IpAddr::from_str("fd00::2").unwrap(),
|
||||
IpAddr::from_str("fd00::3").unwrap(),
|
||||
]);
|
||||
|
||||
let mut v = i.collect::<Vec<_>>();
|
||||
v.reverse();
|
||||
assert_eq!(v, i.rev().collect::<Vec<_>>());
|
||||
|
||||
let i = IpAddrRange::from(Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe").unwrap(),
|
||||
Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(),
|
||||
));
|
||||
|
||||
assert_eq!(i.collect::<Vec<IpAddr>>(), vec![
|
||||
IpAddr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe").unwrap(),
|
||||
IpAddr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(),
|
||||
]);
|
||||
|
||||
// #11 (infinite iterator when start and stop are 0)
|
||||
let zero4 = Ipv4Addr::from_str("0.0.0.0").unwrap();
|
||||
let zero6 = Ipv6Addr::from_str("::").unwrap();
|
||||
|
||||
let mut i = Ipv4AddrRange::new(zero4, zero4);
|
||||
assert_eq!(Some(zero4), i.next());
|
||||
assert_eq!(None, i.next());
|
||||
|
||||
let mut i = Ipv6AddrRange::new(zero6, zero6);
|
||||
assert_eq!(Some(zero6), i.next());
|
||||
assert_eq!(None, i.next());
|
||||
|
||||
// Count
|
||||
let i = Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("10.0.0.0").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.3").unwrap()
|
||||
);
|
||||
assert_eq!(i.count(), 4);
|
||||
|
||||
let i = Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("fd00::").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::3").unwrap(),
|
||||
);
|
||||
assert_eq!(i.count(), 4);
|
||||
|
||||
// Size Hint
|
||||
let i = Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("10.0.0.0").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.3").unwrap()
|
||||
);
|
||||
assert_eq!(i.size_hint(), (4, Some(4)));
|
||||
|
||||
let i = Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("fd00::").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::3").unwrap(),
|
||||
);
|
||||
assert_eq!(i.size_hint(), (4, Some(4)));
|
||||
|
||||
// Size Hint: a range where size clearly overflows usize
|
||||
let i = Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("::").unwrap(),
|
||||
Ipv6Addr::from_str("8000::").unwrap(),
|
||||
);
|
||||
assert_eq!(i.size_hint(), (std::usize::MAX, None));
|
||||
|
||||
// Min, Max, Last
|
||||
let i = Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("10.0.0.0").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.3").unwrap()
|
||||
);
|
||||
assert_eq!(Iterator::min(i), Some(Ipv4Addr::from_str("10.0.0.0").unwrap()));
|
||||
assert_eq!(Iterator::max(i), Some(Ipv4Addr::from_str("10.0.0.3").unwrap()));
|
||||
assert_eq!(i.last(), Some(Ipv4Addr::from_str("10.0.0.3").unwrap()));
|
||||
|
||||
let i = Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("fd00::").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::3").unwrap(),
|
||||
);
|
||||
assert_eq!(Iterator::min(i), Some(Ipv6Addr::from_str("fd00::").unwrap()));
|
||||
assert_eq!(Iterator::max(i), Some(Ipv6Addr::from_str("fd00::3").unwrap()));
|
||||
assert_eq!(i.last(), Some(Ipv6Addr::from_str("fd00::3").unwrap()));
|
||||
|
||||
// Nth
|
||||
let i = Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("10.0.0.0").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.3").unwrap()
|
||||
);
|
||||
assert_eq!(i.clone().nth(0), Some(Ipv4Addr::from_str("10.0.0.0").unwrap()));
|
||||
assert_eq!(i.clone().nth(3), Some(Ipv4Addr::from_str("10.0.0.3").unwrap()));
|
||||
assert_eq!(i.clone().nth(4), None);
|
||||
assert_eq!(i.clone().nth(99), None);
|
||||
let mut i2 = i.clone();
|
||||
assert_eq!(i2.nth(1), Some(Ipv4Addr::from_str("10.0.0.1").unwrap()));
|
||||
assert_eq!(i2.nth(1), Some(Ipv4Addr::from_str("10.0.0.3").unwrap()));
|
||||
assert_eq!(i2.nth(0), None);
|
||||
let mut i3 = i.clone();
|
||||
assert_eq!(i3.nth(99), None);
|
||||
assert_eq!(i3.next(), None);
|
||||
|
||||
let i = Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("fd00::").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::3").unwrap(),
|
||||
);
|
||||
assert_eq!(i.clone().nth(0), Some(Ipv6Addr::from_str("fd00::").unwrap()));
|
||||
assert_eq!(i.clone().nth(3), Some(Ipv6Addr::from_str("fd00::3").unwrap()));
|
||||
assert_eq!(i.clone().nth(4), None);
|
||||
assert_eq!(i.clone().nth(99), None);
|
||||
let mut i2 = i.clone();
|
||||
assert_eq!(i2.nth(1), Some(Ipv6Addr::from_str("fd00::1").unwrap()));
|
||||
assert_eq!(i2.nth(1), Some(Ipv6Addr::from_str("fd00::3").unwrap()));
|
||||
assert_eq!(i2.nth(0), None);
|
||||
let mut i3 = i.clone();
|
||||
assert_eq!(i3.nth(99), None);
|
||||
assert_eq!(i3.next(), None);
|
||||
|
||||
// Nth Back
|
||||
let i = Ipv4AddrRange::new(
|
||||
Ipv4Addr::from_str("10.0.0.0").unwrap(),
|
||||
Ipv4Addr::from_str("10.0.0.3").unwrap()
|
||||
);
|
||||
assert_eq!(i.clone().nth_back(0), Some(Ipv4Addr::from_str("10.0.0.3").unwrap()));
|
||||
assert_eq!(i.clone().nth_back(3), Some(Ipv4Addr::from_str("10.0.0.0").unwrap()));
|
||||
assert_eq!(i.clone().nth_back(4), None);
|
||||
assert_eq!(i.clone().nth_back(99), None);
|
||||
let mut i2 = i.clone();
|
||||
assert_eq!(i2.nth_back(1), Some(Ipv4Addr::from_str("10.0.0.2").unwrap()));
|
||||
assert_eq!(i2.nth_back(1), Some(Ipv4Addr::from_str("10.0.0.0").unwrap()));
|
||||
assert_eq!(i2.nth_back(0), None);
|
||||
let mut i3 = i.clone();
|
||||
assert_eq!(i3.nth_back(99), None);
|
||||
assert_eq!(i3.next(), None);
|
||||
|
||||
let i = Ipv6AddrRange::new(
|
||||
Ipv6Addr::from_str("fd00::").unwrap(),
|
||||
Ipv6Addr::from_str("fd00::3").unwrap(),
|
||||
);
|
||||
assert_eq!(i.clone().nth_back(0), Some(Ipv6Addr::from_str("fd00::3").unwrap()));
|
||||
assert_eq!(i.clone().nth_back(3), Some(Ipv6Addr::from_str("fd00::").unwrap()));
|
||||
assert_eq!(i.clone().nth_back(4), None);
|
||||
assert_eq!(i.clone().nth_back(99), None);
|
||||
let mut i2 = i.clone();
|
||||
assert_eq!(i2.nth_back(1), Some(Ipv6Addr::from_str("fd00::2").unwrap()));
|
||||
assert_eq!(i2.nth_back(1), Some(Ipv6Addr::from_str("fd00::").unwrap()));
|
||||
assert_eq!(i2.nth_back(0), None);
|
||||
let mut i3 = i.clone();
|
||||
assert_eq!(i3.nth_back(99), None);
|
||||
assert_eq!(i3.next(), None);
|
||||
}
|
||||
}
|
||||
1762
zeroidc/vendor/ipnet/src/ipnet.rs
vendored
Normal file
1762
zeroidc/vendor/ipnet/src/ipnet.rs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
86
zeroidc/vendor/ipnet/src/ipnet_schemars.rs
vendored
Normal file
86
zeroidc/vendor/ipnet/src/ipnet_schemars.rs
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
use crate::Ipv4Net;
|
||||
use crate::Ipv6Net;
|
||||
use crate::IpNet;
|
||||
|
||||
use schemars::{JsonSchema, gen::SchemaGenerator, schema::{SubschemaValidation, Schema, SchemaObject, StringValidation, Metadata, SingleOrVec, InstanceType}};
|
||||
|
||||
impl JsonSchema for Ipv4Net {
|
||||
fn schema_name() -> String {
|
||||
"Ipv4Net".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
|
||||
Schema::Object(SchemaObject {
|
||||
metadata: Some(Box::new(Metadata {
|
||||
title: Some("IPv4 network".to_string()),
|
||||
description: Some("An IPv4 address with prefix length".to_string()),
|
||||
examples: vec![
|
||||
schemars::_serde_json::Value::String("0.0.0.0/0".to_string()),
|
||||
schemars::_serde_json::Value::String("192.168.0.0/24".to_string()),
|
||||
],
|
||||
..Default::default()
|
||||
})),
|
||||
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
|
||||
string: Some(Box::new(StringValidation {
|
||||
max_length: Some(18),
|
||||
min_length: None,
|
||||
pattern: Some(r#"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(?:3[0-2]|[1-2][0-9]|[0-9])$"#.to_string()),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
impl JsonSchema for Ipv6Net {
|
||||
fn schema_name() -> String {
|
||||
"Ipv6Net".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
|
||||
Schema::Object(SchemaObject {
|
||||
metadata: Some(Box::new(Metadata {
|
||||
title: Some("IPv6 network".to_string()),
|
||||
description: Some("An IPv6 address with prefix length".to_string()),
|
||||
examples: vec![
|
||||
schemars::_serde_json::Value::String("::/0".to_string()),
|
||||
schemars::_serde_json::Value::String("fd00::/32".to_string()),
|
||||
],
|
||||
..Default::default()
|
||||
})),
|
||||
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
|
||||
string: Some(Box::new(StringValidation {
|
||||
max_length: Some(43),
|
||||
min_length: None,
|
||||
pattern: Some(r#"^[0-9A-Fa-f:\.]+\/(?:[0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$"#.to_string()),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
impl JsonSchema for IpNet {
|
||||
fn schema_name() -> String {
|
||||
"IpNet".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||
Schema::Object(SchemaObject {
|
||||
metadata: Some(Box::new(Metadata {
|
||||
title: Some("IP network".to_string()),
|
||||
description: Some("An IPv4 or IPv6 address with prefix length".to_string()),
|
||||
examples: vec![
|
||||
schemars::_serde_json::Value::String("192.168.0.0/24".to_string()),
|
||||
schemars::_serde_json::Value::String("fd00::/32".to_string()),
|
||||
],
|
||||
..Default::default()
|
||||
})),
|
||||
subschemas: Some(Box::new(
|
||||
SubschemaValidation {
|
||||
one_of: Some(vec![Ipv4Net::json_schema(gen), Ipv6Net::json_schema(gen)]),
|
||||
..Default::default()
|
||||
}
|
||||
)),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
276
zeroidc/vendor/ipnet/src/ipnet_serde.rs
vendored
Normal file
276
zeroidc/vendor/ipnet/src/ipnet_serde.rs
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
use crate::{IpNet, Ipv4Net, Ipv6Net};
|
||||
use std::fmt;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
use serde::{self, Serialize, Deserialize, Serializer, Deserializer};
|
||||
use serde::ser::SerializeTuple;
|
||||
use serde::de::{EnumAccess, Error, VariantAccess, Visitor};
|
||||
|
||||
impl Serialize for IpNet {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
match *self {
|
||||
IpNet::V4(ref a) => a.serialize(serializer),
|
||||
IpNet::V6(ref a) => a.serialize(serializer),
|
||||
}
|
||||
} else {
|
||||
match *self {
|
||||
IpNet::V4(ref a) => serializer.serialize_newtype_variant("IpNet", 0, "V4", a),
|
||||
IpNet::V6(ref a) => serializer.serialize_newtype_variant("IpNet", 1, "V6", a),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for IpNet {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer<'de>
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
struct IpNetVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for IpNetVisitor {
|
||||
type Value = IpNet;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("IPv4 or IPv6 network address")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where E: Error
|
||||
{
|
||||
s.parse().map_err(Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(IpNetVisitor)
|
||||
} else {
|
||||
struct EnumVisitor;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum IpNetKind {
|
||||
V4,
|
||||
V6,
|
||||
}
|
||||
|
||||
impl<'de> Visitor<'de> for EnumVisitor {
|
||||
type Value = IpNet;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("IPv4 or IPv6 network address")
|
||||
}
|
||||
|
||||
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||
where A: EnumAccess<'de>
|
||||
{
|
||||
match data.variant()? {
|
||||
(IpNetKind::V4, v) => v.newtype_variant().map(IpNet::V4),
|
||||
(IpNetKind::V6, v) => v.newtype_variant().map(IpNet::V6),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_enum("IpNet", &["V4", "V6"], EnumVisitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Ipv4Net {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
serializer.serialize_str(&self.to_string())
|
||||
} else {
|
||||
let mut seq = serializer.serialize_tuple(5)?;
|
||||
for octet in &self.addr().octets() {
|
||||
seq.serialize_element(octet)?;
|
||||
}
|
||||
seq.serialize_element(&self.prefix_len())?;
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Ipv4Net {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer<'de>
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
struct IpAddrVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for IpAddrVisitor {
|
||||
type Value = Ipv4Net;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("IPv4 network address")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where E: Error
|
||||
{
|
||||
s.parse().map_err(Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(IpAddrVisitor)
|
||||
} else {
|
||||
let b = <[u8; 5]>::deserialize(deserializer)?;
|
||||
Ipv4Net::new(Ipv4Addr::new(b[0], b[1], b[2], b[3]), b[4]).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Ipv6Net {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
serializer.serialize_str(&self.to_string())
|
||||
} else {
|
||||
let mut seq = serializer.serialize_tuple(17)?;
|
||||
for octet in &self.addr().octets() {
|
||||
seq.serialize_element(octet)?;
|
||||
}
|
||||
seq.serialize_element(&self.prefix_len())?;
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Ipv6Net {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: Deserializer<'de>
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
struct IpAddrVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for IpAddrVisitor {
|
||||
type Value = Ipv6Net;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("IPv6 network address")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where E: Error
|
||||
{
|
||||
s.parse().map_err(Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(IpAddrVisitor)
|
||||
} else {
|
||||
let b = <[u8; 17]>::deserialize(deserializer)?;
|
||||
Ipv6Net::new(Ipv6Addr::new(
|
||||
((b[0] as u16) << 8) | b[1] as u16, ((b[2] as u16) << 8) | b[3] as u16,
|
||||
((b[4] as u16) << 8) | b[5] as u16, ((b[6] as u16) << 8) | b[7] as u16,
|
||||
((b[8] as u16) << 8) | b[9] as u16, ((b[10] as u16) << 8) | b[11] as u16,
|
||||
((b[12] as u16) << 8) | b[13] as u16, ((b[14] as u16) << 8) | b[15] as u16
|
||||
), b[16]).map_err(Error::custom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate serde_test;
|
||||
|
||||
use crate::{IpNet, Ipv4Net, Ipv6Net};
|
||||
use self::serde_test::{assert_tokens, Configure, Token};
|
||||
|
||||
#[test]
|
||||
fn test_serialize_ipnet_v4() {
|
||||
let net_str = "10.1.1.0/24";
|
||||
let net: IpNet = net_str.parse().unwrap();
|
||||
assert_tokens(&net.readable(), &[Token::Str(net_str)]);
|
||||
assert_tokens(&net.compact(), &[
|
||||
Token::NewtypeVariant { name: "IpNet", variant: "V4", },
|
||||
Token::Tuple { len: 5 },
|
||||
Token::U8(10),
|
||||
Token::U8(1),
|
||||
Token::U8(1),
|
||||
Token::U8(0),
|
||||
Token::U8(24),
|
||||
Token::TupleEnd,
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_ipnet_v6() {
|
||||
let net_str = "fd00::/32";
|
||||
let net: IpNet = net_str.parse().unwrap();
|
||||
assert_tokens(&net.readable(), &[Token::Str(net_str)]);
|
||||
assert_tokens(&net.compact(), &[
|
||||
Token::NewtypeVariant { name: "IpNet", variant: "V6", },
|
||||
// This is too painful, but Token::Bytes() seems to be
|
||||
// an array with a length, which is not what we serialize.
|
||||
Token::Tuple { len: 17 },
|
||||
Token::U8(253u8),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(32),
|
||||
Token::TupleEnd,
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_ipv4_net() {
|
||||
let net_str = "10.1.1.0/24";
|
||||
let net: Ipv4Net = net_str.parse().unwrap();
|
||||
assert_tokens(&net.readable(), &[Token::Str(net_str)]);
|
||||
assert_tokens(&net.compact(), &[
|
||||
Token::Tuple { len: 5 },
|
||||
Token::U8(10),
|
||||
Token::U8(1),
|
||||
Token::U8(1),
|
||||
Token::U8(0),
|
||||
Token::U8(24),
|
||||
Token::TupleEnd,
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_ipv6_net() {
|
||||
let net_str = "fd00::/32";
|
||||
let net: Ipv6Net = net_str.parse().unwrap();
|
||||
assert_tokens(&net.readable(), &[Token::Str(net_str)]);
|
||||
assert_tokens(&net.compact(), &[
|
||||
// This is too painful, but Token::Bytes() seems to be
|
||||
// an array with a length, which is not what we serialize.
|
||||
Token::Tuple { len: 17 },
|
||||
Token::U8(253u8),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(0),
|
||||
Token::U8(32),
|
||||
Token::TupleEnd,
|
||||
]);
|
||||
}
|
||||
}
|
||||
96
zeroidc/vendor/ipnet/src/lib.rs
vendored
Normal file
96
zeroidc/vendor/ipnet/src/lib.rs
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
#![doc(html_root_url = "https://docs.rs/ipnet/2.5.0")]
|
||||
//! Types for IPv4 and IPv6 network addresses.
|
||||
//!
|
||||
//! This module provides types and useful methods for working with IPv4
|
||||
//! and IPv6 network addresses, commonly called IP prefixes. The new
|
||||
//! [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`] types build on the existing
|
||||
//! [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`] types already provided in
|
||||
//! Rust's standard library and align to their design to stay
|
||||
//! consistent.
|
||||
//!
|
||||
//! The module also provides the [`IpSubnets`], [`Ipv4Subnets`], and
|
||||
//! [`Ipv6Subnets`] types for iterating over the subnets contained in
|
||||
//! an IP address range. The [`IpAddrRange`], [`Ipv4AddrRange`], and
|
||||
//! [`Ipv6AddrRange`] types for iterating over IP addresses in a range.
|
||||
//! And traits that extend `Ipv4Addr` and `Ipv6Addr` with methods for
|
||||
//! addition, subtraction, bitwise-and, and bitwise-or operations that
|
||||
//! are missing in Rust's standard library.
|
||||
//!
|
||||
//! The module only uses stable features so it is guaranteed to compile
|
||||
//! using the stable toolchain.
|
||||
//!
|
||||
//! # Organization
|
||||
//!
|
||||
//! * [`IpNet`] represents an IP network address, either IPv4 or IPv6.
|
||||
//! * [`Ipv4Net`] and [`Ipv6Net`] are respectively IPv4 and IPv6 network
|
||||
//! addresses.
|
||||
//! * [`IpSubnets`], [`Ipv4Subnets`], and [`Ipv6Subnets`] are iterators
|
||||
//! that generate the smallest set of IP network addresses bound by an
|
||||
//! IP address range and minimum prefix length. These can be created
|
||||
//! using their constructors. They are also returned by the
|
||||
//! [`subnets()`] methods and used within the [`aggregate()`] methods.
|
||||
//! * [`IpAddrRange`], [`Ipv4AddrRange`], and [`Ipv6AddrRange`] are
|
||||
//! iterators that generate IP addresses. These can be created using
|
||||
//! their constructors. They are also returned by the [`hosts()`]
|
||||
//! methods.
|
||||
//! * The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
|
||||
//! the [`Ipv4Addr`] and [`Ipv6Addr`] types with methods to perform
|
||||
//! these operations.
|
||||
//!
|
||||
//! [`IpNet`]: enum.IpNet.html
|
||||
//! [`Ipv4Net`]: struct.Ipv4Net.html
|
||||
//! [`Ipv6Net`]: struct.Ipv6Net.html
|
||||
//! [`IpAddr`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html
|
||||
//! [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
|
||||
//! [`Ipv6Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
|
||||
//! [`IpSubnets`]: enum.IpSubnets.html
|
||||
//! [`Ipv4Subnets`]: struct.Ipv4Subnets.html
|
||||
//! [`Ipv6Subnets`]: struct.Ipv6Subnets.html
|
||||
//! [`subnets()`]: enum.IpNet.html#method.subnets
|
||||
//! [`aggregate()`]: enum.IpNet.html#method.aggregate
|
||||
//! [`IpAddrRange`]: enum.IpAddrRange.html
|
||||
//! [`Ipv4AddrRange`]: struct.Ipv4AddrRange.html
|
||||
//! [`Ipv6AddrRange`]: struct.Ipv6AddrRange.html
|
||||
//! [`hosts()`]: enum.IpNet.html#method.hosts
|
||||
//! [`IpAdd`]: trait.IpAdd.html
|
||||
//! [`IpSub`]: trait.IpSub.html
|
||||
//! [`IpBitAnd`]: trait.IpBitAnd.html
|
||||
//! [`IpBitOr`]: trait.IpBitOr.html
|
||||
//!
|
||||
//! # Serde support
|
||||
//!
|
||||
//! This library comes with support for [serde](https://serde.rs) but
|
||||
//! it's not enabled by default. Use the `serde` [feature] to enable.
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! ipnet = { version = "2", features = ["serde"] }
|
||||
//! ```
|
||||
//!
|
||||
//! For human readable formats (e.g. JSON) the `IpNet`, `Ipv4Net`, and
|
||||
//! `Ipv6Net` types will serialize to their `Display` strings.
|
||||
//!
|
||||
//! For compact binary formats (e.g. Bincode) the `Ipv4Net` and
|
||||
//! `Ipv6Net` types will serialize to a string of 5 and 17 bytes that
|
||||
//! consist of the network address octects followed by the prefix
|
||||
//! length. The `IpNet` type will serialize to an Enum with the V4 or V6
|
||||
//! variant index prepending the above string of 5 or 17 bytes.
|
||||
//!
|
||||
//! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
#[cfg(feature = "schemars")]
|
||||
extern crate schemars;
|
||||
|
||||
pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
|
||||
pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
|
||||
pub use self::parser::AddrParseError;
|
||||
|
||||
mod ipext;
|
||||
mod ipnet;
|
||||
mod parser;
|
||||
#[cfg(feature = "serde")]
|
||||
mod ipnet_serde;
|
||||
#[cfg(feature = "schemars")]
|
||||
mod ipnet_schemars;
|
||||
345
zeroidc/vendor/ipnet/src/parser.rs
vendored
Normal file
345
zeroidc/vendor/ipnet/src/parser.rs
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
//! A private parser implementation of IPv4 and IPv6 network addresses.
|
||||
//!
|
||||
//! The existing `std::net::parser` module cannot be extended because it
|
||||
//! is private. It is copied and extended here with methods for parsing
|
||||
//! IP network addresses.
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::ipnet::{IpNet, Ipv4Net, Ipv6Net};
|
||||
|
||||
pub struct Parser<'a> {
|
||||
// parsing as ASCII, so can use byte array
|
||||
s: &'a [u8],
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
fn new(s: &'a str) -> Parser<'a> {
|
||||
Parser {
|
||||
s: s.as_bytes(),
|
||||
pos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_eof(&self) -> bool {
|
||||
self.pos == self.s.len()
|
||||
}
|
||||
|
||||
// Commit only if parser returns Some
|
||||
fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
|
||||
F: FnOnce(&mut Parser) -> Option<T>,
|
||||
{
|
||||
let pos = self.pos;
|
||||
let r = cb(self);
|
||||
if r.is_none() {
|
||||
self.pos = pos;
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
// Commit only if parser read till EOF
|
||||
fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
|
||||
F: FnOnce(&mut Parser) -> Option<T>,
|
||||
{
|
||||
self.read_atomically(move |p| {
|
||||
match cb(p) {
|
||||
Some(x) => if p.is_eof() {Some(x)} else {None},
|
||||
None => None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Return result of first successful parser
|
||||
fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser) -> Option<T> + 'static>])
|
||||
-> Option<T> {
|
||||
for pf in parsers {
|
||||
if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
|
||||
return Some(r);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Apply 3 parsers sequentially
|
||||
fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
|
||||
pa: PA,
|
||||
pb: PB,
|
||||
pc: PC)
|
||||
-> Option<(A, B, C)> where
|
||||
PA: FnOnce(&mut Parser) -> Option<A>,
|
||||
PB: FnOnce(&mut Parser) -> Option<B>,
|
||||
PC: FnOnce(&mut Parser) -> Option<C>,
|
||||
{
|
||||
self.read_atomically(move |p| {
|
||||
let a = pa(p);
|
||||
let b = if a.is_some() { pb(p) } else { None };
|
||||
let c = if b.is_some() { pc(p) } else { None };
|
||||
match (a, b, c) {
|
||||
(Some(a), Some(b), Some(c)) => Some((a, b, c)),
|
||||
_ => None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Read next char
|
||||
fn read_char(&mut self) -> Option<char> {
|
||||
if self.is_eof() {
|
||||
None
|
||||
} else {
|
||||
let r = self.s[self.pos] as char;
|
||||
self.pos += 1;
|
||||
Some(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Return char and advance iff next char is equal to requested
|
||||
fn read_given_char(&mut self, c: char) -> Option<char> {
|
||||
self.read_atomically(|p| {
|
||||
match p.read_char() {
|
||||
Some(next) if next == c => Some(next),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Read digit
|
||||
fn read_digit(&mut self, radix: u8) -> Option<u8> {
|
||||
fn parse_digit(c: char, radix: u8) -> Option<u8> {
|
||||
let c = c as u8;
|
||||
// assuming radix is either 10 or 16
|
||||
if c >= b'0' && c <= b'9' {
|
||||
Some(c - b'0')
|
||||
} else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
|
||||
Some(c - b'a' + 10)
|
||||
} else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
|
||||
Some(c - b'A' + 10)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
self.read_atomically(|p| {
|
||||
p.read_char().and_then(|c| parse_digit(c, radix))
|
||||
})
|
||||
}
|
||||
|
||||
fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
|
||||
let mut r = 0;
|
||||
let mut digit_count = 0;
|
||||
loop {
|
||||
match self.read_digit(radix) {
|
||||
Some(d) => {
|
||||
r = r * (radix as u32) + (d as u32);
|
||||
digit_count += 1;
|
||||
if digit_count > max_digits || r >= upto {
|
||||
return None
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if digit_count == 0 {
|
||||
return None
|
||||
} else {
|
||||
return Some(r)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Read number, failing if max_digits of number value exceeded
|
||||
fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
|
||||
self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
|
||||
}
|
||||
|
||||
fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
|
||||
let mut bs = [0; 4];
|
||||
let mut i = 0;
|
||||
while i < 4 {
|
||||
if i != 0 && self.read_given_char('.').is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
|
||||
match octet {
|
||||
Some(d) => bs[i] = d,
|
||||
None => return None,
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
|
||||
}
|
||||
|
||||
// Read IPv4 address
|
||||
fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
|
||||
self.read_atomically(|p| p.read_ipv4_addr_impl())
|
||||
}
|
||||
|
||||
fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
|
||||
fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
|
||||
assert!(head.len() + tail.len() <= 8);
|
||||
let mut gs = [0; 8];
|
||||
gs[..head.len()].copy_from_slice(head);
|
||||
gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
|
||||
Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
|
||||
}
|
||||
|
||||
fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
|
||||
-> (usize, bool) {
|
||||
let mut i = 0;
|
||||
while i < limit {
|
||||
if i < limit - 1 {
|
||||
let ipv4 = p.read_atomically(|p| {
|
||||
if i == 0 || p.read_given_char(':').is_some() {
|
||||
p.read_ipv4_addr()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
if let Some(v4_addr) = ipv4 {
|
||||
let octets = v4_addr.octets();
|
||||
groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
|
||||
groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
|
||||
return (i + 2, true);
|
||||
}
|
||||
}
|
||||
|
||||
let group = p.read_atomically(|p| {
|
||||
if i == 0 || p.read_given_char(':').is_some() {
|
||||
p.read_number(16, 4, 0x10000).map(|n| n as u16)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
match group {
|
||||
Some(g) => groups[i] = g,
|
||||
None => return (i, false)
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
(i, false)
|
||||
}
|
||||
|
||||
let mut head = [0; 8];
|
||||
let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
|
||||
|
||||
if head_size == 8 {
|
||||
return Some(Ipv6Addr::new(
|
||||
head[0], head[1], head[2], head[3],
|
||||
head[4], head[5], head[6], head[7]))
|
||||
}
|
||||
|
||||
// IPv4 part is not allowed before `::`
|
||||
if head_ipv4 {
|
||||
return None
|
||||
}
|
||||
|
||||
// read `::` if previous code parsed less than 8 groups
|
||||
if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut tail = [0; 8];
|
||||
let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
|
||||
Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
|
||||
}
|
||||
|
||||
fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
|
||||
self.read_atomically(|p| p.read_ipv6_addr_impl())
|
||||
}
|
||||
|
||||
/* Additions for IpNet below. */
|
||||
|
||||
// Read IPv4 network
|
||||
fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
|
||||
let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
|
||||
let slash = |p: &mut Parser| p.read_given_char('/');
|
||||
let prefix_len = |p: &mut Parser| {
|
||||
p.read_number(10, 2, 33).map(|n| n as u8)
|
||||
};
|
||||
|
||||
self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
|
||||
let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
|
||||
Ipv4Net::new(ip, prefix_len).unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
// Read Ipv6 network
|
||||
fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
|
||||
let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
|
||||
let slash = |p: &mut Parser| p.read_given_char('/');
|
||||
let prefix_len = |p: &mut Parser| {
|
||||
p.read_number(10, 3, 129).map(|n| n as u8)
|
||||
};
|
||||
|
||||
self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
|
||||
let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
|
||||
Ipv6Net::new(ip, prefix_len).unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
fn read_ip_net(&mut self) -> Option<IpNet> {
|
||||
let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
|
||||
let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
|
||||
self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
|
||||
}
|
||||
|
||||
/* Additions for IpNet above. */
|
||||
}
|
||||
|
||||
/* Additions for IpNet below. */
|
||||
|
||||
impl FromStr for IpNet {
|
||||
type Err = AddrParseError;
|
||||
fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
|
||||
match Parser::new(s).read_till_eof(|p| p.read_ip_net()) {
|
||||
Some(s) => Ok(s),
|
||||
None => Err(AddrParseError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Ipv4Net {
|
||||
type Err = AddrParseError;
|
||||
fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
|
||||
match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) {
|
||||
Some(s) => Ok(s),
|
||||
None => Err(AddrParseError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Ipv6Net {
|
||||
type Err = AddrParseError;
|
||||
fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
|
||||
match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) {
|
||||
Some(s) => Ok(s),
|
||||
None => Err(AddrParseError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Additions for IpNet above. */
|
||||
|
||||
/// An error which can be returned when parsing an IP network address.
|
||||
///
|
||||
/// This error is used as the error type for the [`FromStr`] implementation for
|
||||
/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
|
||||
///
|
||||
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
|
||||
/// [`IpNet`]: enum.IpNet.html
|
||||
/// [`Ipv4Net`]: struct.Ipv4Net.html
|
||||
/// [`Ipv6Net`]: struct.Ipv6Net.html
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct AddrParseError(());
|
||||
|
||||
impl fmt::Display for AddrParseError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.write_str("invalid IP address syntax")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for AddrParseError {}
|
||||
Reference in New Issue
Block a user