| Crates.io | cidr_block |
| lib.rs | cidr_block |
| version | 0.1.0 |
| created_at | 2025-08-07 09:17:08.851065+00 |
| updated_at | 2025-08-07 09:17:08.851065+00 |
| description | A library for CIDR block manipulation in Rust which provides utilities to parse, validate, and manipulate CIDR notation and get individual ip addresses. |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1784961 |
| size | 17,997 |
A Rust library for CIDR block manipulation that provides utilities to parse, validate, and manipulate CIDR notation and get individual IP addresses.
Add this to your Cargo.toml:
[dependencies]
cidr_block = "0.1.0"
Or use the cargo command:
cargo add cidr_block
use cidr_block::v4_num_ips;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Calculate how many IP addresses are in a /24 network
let num_ips = v4_num_ips("192.168.1.0/24")?;
assert_eq!(num_ips, 256); // A /24 network has 256 IP addresses
// Calculate how many IP addresses are in a /16 network
let num_ips = v4_num_ips("10.0.0.0/16")?;
assert_eq!(num_ips, 65536); // A /16 network has 65536 IP addresses
Ok(())
}
use cidr_block::next_ip_v4;
use std::net::Ipv4Addr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Parse an IP address
let ip: Ipv4Addr = "192.168.1.1".parse()?;
// Get the next IP address in the /24 network (increment by 1)
let next_ip = next_ip_v4(ip, 24, 1)?;
assert_eq!(next_ip, "192.168.1.2".parse::<Ipv4Addr>()?);
// Skip 10 IP addresses
let next_ip = next_ip_v4(ip, 24, 10)?;
assert_eq!(next_ip, "192.168.1.11".parse::<Ipv4Addr>()?);
// Demonstrate wrapping behavior at the end of the CIDR block
let last_ip: Ipv4Addr = "192.168.1.255".parse()?;
let next_ip = next_ip_v4(last_ip, 24, 1)?;
assert_eq!(next_ip, "192.168.1.0".parse::<Ipv4Addr>()?);
Ok(())
}
use cidr_block::IPExt;
use std::net::Ipv4Addr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Calculate number of IPs using the trait method
let num_ips = Ipv4Addr::num_ips("192.168.1.0/24")?;
assert_eq!(num_ips, 256);
// Get the next IP using the trait method
let ip: Ipv4Addr = "192.168.1.1".parse()?;
let next_ip = ip.next_ip(24, 1)?;
assert_eq!(next_ip, "192.168.1.2".parse::<Ipv4Addr>()?);
Ok(())
}
use cidr_block::v6_num_ips;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Calculate how many IP addresses are in a /64 network
let num_ips = v6_num_ips("2001:db8::/64")?;
assert_eq!(num_ips, 18_446_744_073_709_551_616u128); // 2^64 addresses
// Calculate how many IP addresses are in a /128 network (just one)
let num_ips = v6_num_ips("2001:db8::1/128")?;
assert_eq!(num_ips, 1);
Ok(())
}
use cidr_block::next_ip_v6;
use std::net::Ipv6Addr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Parse an IPv6 address
let ip: Ipv6Addr = "2001:db8::1".parse()?;
// Get the next IP address in the /64 network (increment by 1)
let next_ip = next_ip_v6(ip, 64, 1)?;
assert_eq!(next_ip, "2001:db8::2".parse::<Ipv6Addr>()?);
// Skip 10 IP addresses
let next_ip = next_ip_v6(ip, 64, 10)?;
assert_eq!(next_ip, "2001:db8::b".parse::<Ipv6Addr>()?);
// Demonstrate wrapping behavior with large increments
let ip: Ipv6Addr = "2001:db8::ffff".parse()?;
let next_ip = next_ip_v6(ip, 64, 2)?;
assert_eq!(next_ip, "2001:db8::1".parse::<Ipv6Addr>()?);
Ok(())
}
use cidr_block::IPExt;
use std::net::Ipv6Addr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Calculate number of IPs using the trait method
let num_ips = Ipv6Addr::num_ips("2001:db8::/64")?;
// Get the next IP using the trait method
let ip: Ipv6Addr = "2001:db8::1".parse()?;
let next_ip = ip.next_ip(64, 1)?;
assert_eq!(next_ip, "2001:db8::2".parse::<Ipv6Addr>()?);
Ok(())
}
v4_num_ips(block: &str) -> Result<u32, Error>Calculates the number of IP addresses in an IPv4 CIDR block.
block: A string slice that represents the IPv4 CIDR block (e.g., "192.168.0.0/24").Ok(u32): The number of IP addresses in the block.Err(Error): If the block format is invalid or if the prefix length is out of range.next_ip_v4(ip: Ipv4Addr, prefix_length: u8, n: u32) -> Result<Ipv4Addr, Error>Calculates the next IPv4 address within the same CIDR block, wrapping around if necessary.
ip: An Ipv4Addr that represents the starting IPv4 address.prefix_length: The prefix length of the CIDR block (e.g., 24 for a /24 network).n: The number of addresses to skip.Ok(Ipv4Addr): The next IPv4 address within the CIDR block.Err(Error): If the prefix length is invalid (greater than 32).v6_num_ips(block: &str) -> Result<u128, Error>Calculates the number of IP addresses in an IPv6 CIDR block.
block: A string slice that represents the IPv6 CIDR block (e.g., "2001:db8::/64").Ok(u128): The number of IP addresses in the block.Err(Error): If the block format is invalid or if the prefix length is out of range.next_ip_v6(ip: Ipv6Addr, prefix_length: u8, n: u128) -> Result<Ipv6Addr, Error>Calculates the next IPv6 address within the same CIDR block, wrapping around if necessary.
ip: An Ipv6Addr that represents the starting IPv6 address.prefix_length: The prefix length of the CIDR block (e.g., 64 for a /64 network).n: The number of addresses to skip.Ok(Ipv6Addr): The next IPv6 address within the CIDR block.Err(Error): If the prefix length is invalid (greater than 128).IPExt TraitThe IPExt trait provides a unified interface for both IPv4 and IPv6 address types.
pub trait IPExt: Clone + Copy {
type Error;
type LenType;
fn next_ip(&self, prefix_length: u8, n: Self::LenType) -> Result<Self, Self::Error>
where
Self: Sized;
fn num_ips(block: &str) -> Result<Self::LenType, Self::Error>
where
Self: Sized;
}
This trait is implemented for both Ipv4Addr and Ipv6Addr types, allowing for a more ergonomic API when working with different IP address families.
Error Enumpub enum Error {
InvalidBlock,
InvalidPrefixLength,
}
This project is licensed under the MIT License - see the LICENSE file for details.