mirror of
https://github.com/achanda/ipnetwork.git
synced 2025-06-19 18:07:45 +00:00
Implement an iterator for Ipv4Network
This commit is contained in:
63
src/lib.rs
63
src/lib.rs
@ -37,6 +37,25 @@ pub enum IpNetworkError {
|
|||||||
InvalidCidrFormat(String),
|
InvalidCidrFormat(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Ipv4NetworkIterator {
|
||||||
|
next: u64,
|
||||||
|
end: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for Ipv4NetworkIterator {
|
||||||
|
type Item = Ipv4Addr;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Ipv4Addr> {
|
||||||
|
if self.next < self.end {
|
||||||
|
let next = Ipv4Addr::from(self.next as u32);
|
||||||
|
self.next += 1;
|
||||||
|
Some(next)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Ipv4Network {
|
impl Ipv4Network {
|
||||||
/// Constructs a new `Ipv4Network` from any `Ipv4Addr` and a prefix denoting the network size.
|
/// Constructs a new `Ipv4Network` from any `Ipv4Addr` and a prefix denoting the network size.
|
||||||
/// If the prefix is larger than 32 this will return an `IpNetworkError::InvalidPrefix`.
|
/// If the prefix is larger than 32 this will return an `IpNetworkError::InvalidPrefix`.
|
||||||
@ -51,6 +70,18 @@ impl Ipv4Network {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over `Ipv4Network`. Each call to `next` will return the next
|
||||||
|
/// `Ipv4Addr` in the given network. `None` will be returned when there are no more
|
||||||
|
/// addresses.
|
||||||
|
pub fn iter(&self) -> Ipv4NetworkIterator {
|
||||||
|
let (_, start) = self.network();
|
||||||
|
let end = start as u64 + self.size();
|
||||||
|
Ipv4NetworkIterator {
|
||||||
|
next: start as u64,
|
||||||
|
end: end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_cidr(cidr: &str) -> Result<Ipv4Network, IpNetworkError> {
|
pub fn from_cidr(cidr: &str) -> Result<Ipv4Network, IpNetworkError> {
|
||||||
let (addr_str, prefix_str) = try!(cidr_parts(cidr));
|
let (addr_str, prefix_str) = try!(cidr_parts(cidr));
|
||||||
let addr = try!(Self::parse_addr(addr_str));
|
let addr = try!(Self::parse_addr(addr_str));
|
||||||
@ -439,4 +470,36 @@ mod test {
|
|||||||
let ip = Ipv4Addr::new(10, 1, 0, 1);
|
let ip = Ipv4Addr::new(10, 1, 0, 1);
|
||||||
assert!(!cidr.contains(ip));
|
assert!(!cidr.contains(ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn iterator_v4() {
|
||||||
|
let cidr = Ipv4Network::from_cidr("192.168.122.0/30").unwrap();
|
||||||
|
let mut iter = cidr.iter();
|
||||||
|
assert_eq!(Ipv4Addr::new(192, 168, 122, 0), iter.next().unwrap());
|
||||||
|
assert_eq!(Ipv4Addr::new(192, 168, 122, 1), iter.next().unwrap());
|
||||||
|
assert_eq!(Ipv4Addr::new(192, 168, 122, 2), iter.next().unwrap());
|
||||||
|
assert_eq!(Ipv4Addr::new(192, 168, 122, 3), iter.next().unwrap());
|
||||||
|
assert_eq!(None, iter.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn iterator_v4_tiny() {
|
||||||
|
let cidr = Ipv4Network::from_cidr("10/32").unwrap();
|
||||||
|
let mut iter = cidr.iter();
|
||||||
|
assert_eq!(Ipv4Addr::new(10, 0, 0, 0), iter.next().unwrap());
|
||||||
|
assert_eq!(None, iter.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests the entire IPv4 space to see if the iterator will stop at the correct place
|
||||||
|
// and not overflow or wrap around. Ignored since it takes a long time to run.
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn iterator_v4_huge() {
|
||||||
|
let cidr = Ipv4Network::from_cidr("0/0").unwrap();
|
||||||
|
let mut iter = cidr.iter();
|
||||||
|
for i in 0..(u32::max_value() as u64 + 1) {
|
||||||
|
assert_eq!(i as u32, u32::from(iter.next().unwrap()));
|
||||||
|
}
|
||||||
|
assert_eq!(None, iter.next());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user