cidr_block

Crates.iocidr_block
lib.rscidr_block
version0.1.0
created_at2025-08-07 09:17:08.851065+00
updated_at2025-08-07 09:17:08.851065+00
descriptionA 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
id1784961
size17,997
TA3PKS (ta3pks)

documentation

README

CIDR Block

License: MIT

A Rust library for CIDR block manipulation that provides utilities to parse, validate, and manipulate CIDR notation and get individual IP addresses.

Features

  • Calculate the number of IP addresses in IPv4 and IPv6 CIDR blocks
  • Generate the next IP address within a CIDR block with wrapping behavior
  • Support for both IPv4 and IPv6 address families
  • Trait-based extensions for IP address types
  • Error handling for invalid CIDR blocks and prefix lengths

Installation

Add this to your Cargo.toml:

[dependencies]
cidr_block = "0.1.0"

Or use the cargo command:

cargo add cidr_block

Usage Examples

IPv4 Examples

Calculate the number of IP addresses in a 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(())
}

Get the next IP address in a CIDR block

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(())
}

Using the trait-based API

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(())
}

IPv6 Examples

Calculate the number of IP addresses in a CIDR block

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(())
}

Get the next IP address in a CIDR block

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(())
}

Using the trait-based API

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(())
}

API Reference

IPv4 Functions

v4_num_ips(block: &str) -> Result<u32, Error>

Calculates the number of IP addresses in an IPv4 CIDR block.

  • Parameters:
    • block: A string slice that represents the IPv4 CIDR block (e.g., "192.168.0.0/24").
  • Returns:
    • 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.

  • Parameters:
    • 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.
  • Returns:
    • Ok(Ipv4Addr): The next IPv4 address within the CIDR block.
    • Err(Error): If the prefix length is invalid (greater than 32).

IPv6 Functions

v6_num_ips(block: &str) -> Result<u128, Error>

Calculates the number of IP addresses in an IPv6 CIDR block.

  • Parameters:
    • block: A string slice that represents the IPv6 CIDR block (e.g., "2001:db8::/64").
  • Returns:
    • 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.

  • Parameters:
    • 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.
  • Returns:
    • Ok(Ipv6Addr): The next IPv6 address within the CIDR block.
    • Err(Error): If the prefix length is invalid (greater than 128).

Trait-based API

IPExt Trait

The 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 Types

Error Enum

pub enum Error {
    InvalidBlock,
    InvalidPrefixLength,
}
  • InvalidBlock: Returned when the CIDR block format is invalid.
  • InvalidPrefixLength: Returned when the prefix length is out of range (greater than 32 for IPv4 or greater than 128 for IPv6).

License

This project is licensed under the MIT License - see the LICENSE file for details.

Commit count: 0

cargo fmt