#![no_std]
#![warn(missing_docs)]
#![allow(clippy::style)]
mod parser;
pub use parser::{parse_ip, ParseError};
pub mod base;
pub mod v4;
pub mod v6;
use core::{fmt, net};
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Cidr {
V4(v4::Cidr),
V6(v6::Cidr),
}
impl Cidr {
pub const IPV4_BITS: u8 = v4::BITS_LEN;
pub const IPV6_BITS: u8 = v6::BITS_LEN;
#[inline(always)]
pub const fn new(addr: net::IpAddr, prefix: u8) -> Option<Self> {
match addr {
net::IpAddr::V4(addr) => Self::new_v4(addr, prefix),
net::IpAddr::V6(addr) => Self::new_v6(addr, prefix),
}
}
#[inline]
pub const fn new_v4(addr: net::Ipv4Addr, prefix: u8) -> Option<Self> {
match v4::Cidr::new(addr, prefix) {
Some(cidr) => Some(Self::V4(cidr)),
None => None,
}
}
#[inline]
pub const fn new_v6(addr: net::Ipv6Addr, prefix: u8) -> Option<Self> {
match v6::Cidr::new(addr, prefix) {
Some(cidr) => Some(Self::V6(cidr)),
None => None,
}
}
#[inline(always)]
pub const fn addr(&self) -> net::IpAddr {
match self {
Self::V4(cidr) => net::IpAddr::V4(cidr.addr()),
Self::V6(cidr) => net::IpAddr::V6(cidr.addr()),
}
}
#[inline(always)]
pub const fn prefix(&self) -> u8 {
match self {
Self::V4(cidr) => cidr.prefix(),
Self::V6(cidr) => cidr.prefix(),
}
}
#[inline(always)]
pub const fn network_addr(&self) -> net::IpAddr {
match self {
Self::V4(cidr) => net::IpAddr::V4(cidr.network_addr()),
Self::V6(cidr) => net::IpAddr::V6(cidr.network_addr()),
}
}
#[inline(always)]
pub const fn broadcast_addr(&self) -> net::IpAddr {
match self {
Self::V4(cidr) => net::IpAddr::V4(cidr.broadcast_addr()),
Self::V6(cidr) => net::IpAddr::V6(cidr.broadcast_addr()),
}
}
#[inline(always)]
pub const fn size(&self) -> u128 {
match self {
Self::V4(cidr) => cidr.size() as _,
Self::V6(cidr) => cidr.size(),
}
}
#[inline(always)]
pub const fn contains(&self, addr: net::IpAddr) -> bool {
match (self, addr) {
(Self::V4(cidr), net::IpAddr::V4(addr)) => cidr.contains(addr),
(Self::V6(cidr), net::IpAddr::V6(addr)) => cidr.contains(addr),
_ => false,
}
}
#[inline(always)]
pub const fn get(&self, idx: u128) -> Option<net::IpAddr> {
match self {
Self::V4(cidr) => match cidr.get(idx as u32) {
Some(ip) => Some(net::IpAddr::V4(ip)),
None => None,
}
Self::V6(cidr) => match cidr.get(idx) {
Some(ip) => Some(net::IpAddr::V6(ip)),
None => None,
}
}
}
#[inline(always)]
pub const fn get_unchecked(&self, idx: u128) -> net::IpAddr {
match self {
Self::V4(cidr) => net::IpAddr::V4(cidr.get_unchecked(idx as u32)),
Self::V6(cidr) => net::IpAddr::V6(cidr.get_unchecked(idx)),
}
}
}
impl fmt::Display for Cidr {
#[inline(always)]
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::V4(cidr) => fmt::Display::fmt(cidr, fmt),
Self::V6(cidr) => fmt::Display::fmt(cidr, fmt),
}
}
}
#[inline]
pub const fn parse_cidr(text: &str) -> Result<Option<Cidr>, parser::ParseError<'_>> {
match parse_ip(text) {
Ok((net::IpAddr::V4(addr), None)) => Ok(Some(Cidr::V4(v4::Cidr::new_single(addr)))),
Ok((net::IpAddr::V4(addr), Some(prefix))) => Ok(Cidr::new_v4(addr, prefix)),
Ok((net::IpAddr::V6(addr), None)) => Ok(Some(Cidr::V6(v6::Cidr::new_single(addr)))),
Ok((net::IpAddr::V6(addr), Some(prefix))) => Ok(Cidr::new_v6(addr, prefix)),
Err(error) => Err(error)
}
}