use {
core::str::FromStr,
crate::{Error, IPv4ComponentRange},
};
#[cfg(feature="iter")]
#[doc(cfg(feature="iter"))]
mod ip_v4_range_iter;
#[cfg(feature="iter")]
#[doc(cfg(feature="iter"))]
pub use self::ip_v4_range_iter::*;
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
pub struct IPv4Range {
a: IPv4ComponentRange,
b: IPv4ComponentRange,
c: IPv4ComponentRange,
d: IPv4ComponentRange,
}
impl FromStr for IPv4Range {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
const MAX_LEN: usize = 64;
if s.len() > MAX_LEN {
return Err(err!("String is too long, max length supported: {} bytes", MAX_LEN));
}
let mut parts = s.trim().split('.');
match (parts.next(), parts.next(), parts.next(), parts.next(), parts.next()) {
(Some(a), Some(b), Some(c), Some(d), None) => Ok(Self {
a: IPv4ComponentRange::from_str(a)?,
b: IPv4ComponentRange::from_str(b)?,
c: IPv4ComponentRange::from_str(c)?,
d: IPv4ComponentRange::from_str(d)?,
}),
_ => Err(err!("Invalid IPv4 range: {:?}", s)),
}
}
}
impl<A, B, C, D> From<(A, B, C, D)> for IPv4Range
where A: Into<IPv4ComponentRange>, B: Into<IPv4ComponentRange>, C: Into<IPv4ComponentRange>, D: Into<IPv4ComponentRange> {
fn from((a, b, c, d): (A, B, C, D)) -> Self {
Self {
a: a.into(),
b: b.into(),
c: c.into(),
d: d.into(),
}
}
}
#[test]
fn tests() -> crate::Result<()> {
for s in &["0.0.0.0", "[255,255].[255,255].[255,255].[255,255]", "192.168.[0,9].[9,10)", "192.168.[ 0 ,9].[9 , 10)"] {
IPv4Range::from_str(s)?;
}
for s in &["0.0.0", "192.168.[09].[9-10)", "192.168.[ 0 ,9.9 , 10)"] {
IPv4Range::from_str(s).unwrap_err();
}
Ok(())
}