Functional Weave
Code in Rust

net.cidr

CIDR blocks: network, broadcast, first and last host, host count, netmask and prefix, and membership.

1.0.0 · published 2026-10-03 by charlie · Anterra

Pinned by 70 tests, run in TypeScript, Python and Rust.cidrInfo 15 · cidrContains 18 · isCidr 13 · prefixToNetmask 12 · netmaskToPrefix 12

What it does

A subnet calculator as five functions that only make sense together: describe an IPv4 block (`cidrInfo`), test membership for IPv4 or IPv6 (`cidrContains`), check a block without raising (`isCidr`), and convert between prefix lengths and dotted netmasks.

## Decisions

The functions

A group: 5 functions that work together, each in its own file, each pinned by its own tests in TypeScript, Python and Rust. A project can install only the ones it calls.

  1. cidr_info (cidr: string) -> CidrInfo
  2. cidr_contains (cidr: string, address: string) -> bool
  3. is_cidr (text: string) -> bool
  4. prefix_to_netmask (prefix: int) -> string
  5. netmask_to_prefix (netmask: string) -> int

The type it declares, generated into your project

/// Everything a subnet calculator shows for one IPv4 block.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CidrInfo {
    /// the block with host bits cleared, e.g. 192.168.1.0/24
    pub cidr: String,
    pub network: String,
    pub prefix: i64,
    pub netmask: String,
    /// the inverse mask, as ACLs write it
    pub wildcard: String,
    /// null for /31 and /32, which have none
    pub broadcast: Option<String>,
    pub first_host: String,
    pub last_host: String,
    /// usable addresses: all of them for /31 (RFC 3021) and /32
    pub host_count: i64,
    pub address_count: i64,
}

Once installed, your code imports each one from the group's module.

cidr_info throws on bad input 15 tests

pub fn cidr_info(cidr: &str) -> CidrInfo
cidrstringan IPv4 block, address/prefix, e.g. 192.168.1.0/24; host bits may be set and are dropped
returnsCidrInfo

For example

  • cidr_info(192.168.1.0/24) → cidr 192.168.1.0/24, network 192.168.1.0, prefix 24, netmask 255.255.255.0, wildcard 0.0.0.255, broadcast 192.168.1.255, first host 192.168.1.1, last host 192.168.1.254, host coun… a /24
  • cidr_info(192.168.1.77/24) → cidr 192.168.1.0/24, network 192.168.1.0, prefix 24, netmask 255.255.255.0, wildcard 0.0.0.255, broadcast 192.168.1.255, first host 192.168.1.1, last host 192.168.1.254, host coun… an interface address: host bits are dropped
  • cidr_info(10.0.0.0/8) → cidr 10.0.0.0/8, network 10.0.0.0, prefix 8, netmask 255.0.0.0, wildcard 0.255.255.255, broadcast 10.255.255.255, first host 10.0.0.1, last host 10.255.255.254, host count 16,777,… a /8
fune!(net.cidr@^1);  // then call cidr_info(…)
impl/rust/cidr_info.rs · 59 lines · open · raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::net_cidr_is_cidr::cidr_block;  ← isCidr, another function of this group · built into the same file, even by a slim install
use super::net_ipv4_format_ipv4::format_ipv4;

/// Everything a subnet calculator shows for one IPv4 block.
///
/// Host bits in the input are dropped (192.168.1.77/24 describes
/// 192.168.1.0/24). A /31 is a point-to-point link with two usable addresses
/// and no broadcast (RFC 3021); a /32 is one host.
///
/// # Panics
/// Panics on a malformed block or an IPv6 block.
pub fn cidr_info(cidr: &str) -> CidrInfo {
    let (version, bits, prefix) = match cidr_block(cidr) {
        Some(block) => block,
        None => panic!("\"{}\" is not a CIDR block", cidr),
    };
    if version != 4 {
        panic!("cidrInfo handles IPv4 blocks only, received \"{}\"", cidr);
    }
    let size: i64 = 1 << (32 - prefix);
    let network = bits[0] - bits[0] % size;
    let last = network + size - 1;
    let point_to_point = prefix >= 31;
    CidrInfo {
        cidr: format!("{}/{}", format_ipv4(network), prefix),
        network: format_ipv4(network),
        prefix,
        netmask: format_ipv4(4294967296 - size),
        wildcard: format_ipv4(size - 1),
        broadcast: if point_to_point { None } else { Some(format_ipv4(last)) },
        first_host: format_ipv4(if point_to_point { network } else { network + 1 }),
        last_host: format_ipv4(if point_to_point { last } else { last - 1 }),
        host_count: if point_to_point { size } else { size - 2 },
        address_count: size,
    }
}

pub fn cidr_info_to_value(info: &CidrInfo) -> Value {
    Value::obj(vec![
        ("cidr", Value::str(&info.cidr)),
        ("network", Value::str(&info.network)),
        ("prefix", Value::Int(info.prefix)),
        ("netmask", Value::str(&info.netmask)),
        ("wildcard", Value::str(&info.wildcard)),
        ("broadcast", match &info.broadcast {
            Some(b) => Value::str(b),
            None => Value::Null,
        }),
        ("firstHost", Value::str(&info.first_host)),
        ("lastHost", Value::str(&info.last_host)),
        ("hostCount", Value::Int(info.host_count)),
        ("addressCount", Value::Int(info.address_count)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    cidr_info_to_value(&cidr_info(args[0].as_str()))
}

cidr_contains throws on bad input 18 tests

pub fn cidr_contains(cidr: &str, address: &str) -> bool
cidrstringan IPv4 or IPv6 block
addressstringan IPv4 or IPv6 address; one of the other family is never contained
returnsbool

For example

  • cidr_contains(192.168.1.0/24, 192.168.1.200) → true inside a /24
  • cidr_contains(192.168.1.0/24, 192.168.2.1) → false the next /24 is outside
  • cidr_contains(10.0.0.0/8, 10.255.255.255) → true the last address of a /8
fune!(net.cidr@^1);  // then call cidr_contains(…)
impl/rust/cidr_contains.rs · 48 lines · open · raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::net_cidr_is_cidr::cidr_block;  ← isCidr, another function of this group · built into the same file, even by a slim install
use super::net_ipv4_parse_ipv4::ipv4_value;
use super::net_ipv6_parse_ipv6::ipv6_groups;

/// Whether an address lies inside a block, IPv4 or IPv6.
///
/// An address of the other family is never inside (an IPv4-mapped IPv6
/// address is not treated as its IPv4 address).
///
/// # Panics
/// Panics on a malformed block or address.
pub fn cidr_contains(cidr: &str, address: &str) -> bool {
    let (version, bits, prefix) = match cidr_block(cidr) {
        Some(block) => block,
        None => panic!("\"{}\" is not a CIDR block", cidr),
    };
    let v4 = ipv4_value(address);
    let v6 = if v4.is_none() { ipv6_groups(address) } else { None };
    if v4.is_none() && v6.is_none() {
        panic!("\"{}\" is not an IP address", address);
    }
    if version == 4 {
        return match v4 {
            None => false,
            Some(a) => {
                let size: i64 = 1 << (32 - prefix);
                a / size == bits[0] / size
            }
        };
    }
    let groups = match v6 {
        None => return false,
        Some(g) => g,
    };
    for i in 0..8 {
        let taken = (prefix - 16 * i as i64).clamp(0, 16);
        let size: i64 = 1 << (16 - taken);
        if groups[i] / size != bits[i] / size {
            return false;
        }
    }
    true
}

pub fn fune_vector(args: &[Value]) -> Value {
    Value::Bool(cidr_contains(args[0].as_str(), args[1].as_str()))
}

is_cidr 13 tests

pub fn is_cidr(text: &str) -> bool
textstringany text; true for a well-formed IPv4 or IPv6 block
returnsbool

For example

  • is_cidr(10.0.0.0/8) → true an IPv4 block
  • is_cidr(2001:db8::/32) → true an IPv6 block
  • is_cidr(0.0.0.0/0) → true /0
fune!(net.cidr@^1);  // then call is_cidr(…)
impl/rust/is_cidr.rs · 41 lines · open · raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::net_ipv4_parse_ipv4::ipv4_value;
use super::net_ipv6_parse_ipv6::ipv6_groups;

/// True for a well-formed IPv4 (prefix 0-32) or IPv6 (prefix 0-128) block; never panics.
pub fn is_cidr(text: &str) -> bool {
    cidr_block(text).is_some()
}

// Exported for the other functions of this group; not part of its contract.

/// The block as (version, bits, prefix): bits is [address] for version 4 and
/// the eight groups for version 6. None when the text is not address/prefix
/// with a strict decimal prefix.
pub fn cidr_block(text: &str) -> Option<(i64, Vec<i64>, i64)> {
    let mut halves = text.split('/');
    let address = halves.next()?;
    let digits = halves.next()?;
    if halves.next().is_some() {
        return None;
    }
    let bytes = digits.as_bytes();
    if bytes.is_empty() || bytes.len() > 3 || !bytes.iter().all(|b| b.is_ascii_digit()) {
        return None;
    }
    if bytes.len() > 1 && bytes[0] == b'0' {
        return None;
    }
    let prefix = bytes.iter().fold(0i64, |acc, b| acc * 10 + (b - b'0') as i64);
    if let Some(v4) = ipv4_value(address) {
        return if prefix <= 32 { Some((4, vec![v4], prefix)) } else { None };
    }
    if let Some(v6) = ipv6_groups(address) {
        return if prefix <= 128 { Some((6, v6, prefix)) } else { None };
    }
    None
}

pub fn fune_vector(args: &[Value]) -> Value {
    Value::Bool(is_cidr(args[0].as_str()))
}

prefix_to_netmask throws on bad input 12 tests

pub fn prefix_to_netmask(prefix: i64) -> String
prefixint0 to 32
returnsstring

For example

  • prefix_to_netmask(24) → 255.255.255.0 /24
  • prefix_to_netmask(0) → 0.0.0.0 /0
  • prefix_to_netmask(8) → 255.0.0.0 /8
fune!(net.cidr@^1);  // then call prefix_to_netmask(…)
impl/rust/prefix_to_netmask.rs · 21 lines · open · raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::net_ipv4_format_ipv4::format_ipv4;

/// The dotted-quad mask for a prefix length: 24 is 255.255.255.0.
///
/// # Panics
/// Panics when the prefix is outside 0 to 32.
pub fn prefix_to_netmask(prefix: i64) -> String {
    if !(0..=32).contains(&prefix) {
        panic!("prefix must be an integer from 0 to 32, received {}", prefix);
    }
    format_ipv4(4294967296 - (1i64 << (32 - prefix)))
}

pub fn fune_vector(args: &[Value]) -> Value {
    let prefix = match &args[0] {
        Value::Int(i) => *i,
        other => panic!("prefix must be an integer from 0 to 32, received {}", other),
    };
    Value::str(&prefix_to_netmask(prefix))
}

netmask_to_prefix throws on bad input 12 tests

pub fn netmask_to_prefix(netmask: &str) -> i64
netmaskstringa dotted-quad mask whose one bits are contiguous from the left
returnsint

For example

  • netmask_to_prefix(255.255.255.0) → 24 255.255.255.0 is /24
  • netmask_to_prefix(0.0.0.0) → 0 all zeros is /0
  • netmask_to_prefix(255.255.255.255) → 32 all ones is /32
fune!(net.cidr@^1);  // then call netmask_to_prefix(…)
impl/rust/netmask_to_prefix.rs · 21 lines · open · raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::net_ipv4_parse_ipv4::parse_ipv4;

/// The prefix length of a dotted-quad mask; a mask with a gap in its one bits is refused.
///
/// # Panics
/// Panics on text that is not a dotted quad, or a non-contiguous mask.
pub fn netmask_to_prefix(netmask: &str) -> i64 {
    let value = parse_ipv4(netmask);
    let host_part = 4294967295 - value + 1;
    for prefix in 0..=32i64 {
        if (1i64 << (32 - prefix)) == host_part {
            return prefix;
        }
    }
    panic!("\"{}\" is not a contiguous netmask", netmask);
}

pub fn fune_vector(args: &[Value]) -> Value {
    Value::Int(netmask_to_prefix(args[0].as_str()))
}

Install

fune build

With that line in your source, in a Rust project (language rust in fune.project), fune build resolves it and its 2 dependencies, pins them in fune.lock, downloads only the Rust package of each, and builds the code above into your project’s .fune/build, one readable file per capability with a header linking back here. A crate’s build.rs runs it before every compile. Or pin a range in fune.project and build in one step:

fune add net.cidr

That builds the whole group. To build only what you call, and whatever it uses inside the group:

fune add net.cidr --only cidrInfo
Download for Rust net.cidr-1.0.0-rust.fune · 26,083 bytes sha256 2c3bcb43527ef69ec9041dcdcba2b73f838e74ca486bdc791b93747f69258d5b

The manifest, vectors and README with only the Rust implementation. Install it without the registry with fune add ./net.cidr-1.0.0-rust.fune, or fetch it from a terminal with fune pull net.cidr@1.0.0:rust.

The whole function, every language, is one file too: net.cidr-1.0.0.fune, 36,244 bytes, sha256 bbc5cdb055ae733750b3c2cfb9061a67690545d83a9deae6e546ea7de67c4510. It installs into a project of any language.

Customise it in your app

The seams this capability offers. Put a marker directly above a function of your own and fune build wires it into the built code; the package on the registry is not changed, the built file’s header lists it under CUSTOMISED, and fune hooks lists every hook in the project. How hooks work.

before — your function gets the arguments and returns them, changed or not, or throws to refuse the call.

// fune: before net.cidr.cidrInfo
// fune: before net.cidr.cidrContains
// fune: before net.cidr.isCidr
// fune: before net.cidr.prefixToNetmask
// fune: before net.cidr.netmaskToPrefix

after — your function gets the result and the arguments, and returns the final result.

// fune: after net.cidr.cidrInfo
// fune: after net.cidr.cidrContains
// fune: after net.cidr.isCidr
// fune: after net.cidr.prefixToNetmask
// fune: after net.cidr.netmaskToPrefix

replace — inside this capability’s code only, calls to a dependency go to your function, with the same signature. Other capabilities that use it are unaffected; write in * to replace it everywhere.

// fune: replace net.ipv4 in net.cidr
// fune: replace net.ipv6 in net.cidr

step — your function runs at a numbered point inside a function’s body, receives the in-scope values it names as parameters, and may return replacements. List the points with fune show net.cidr --steps.

// fune: step net.cidr.<fn> after <n|label>

Tests

A version published now needs at least 8 tests for every function, and one that expects the error for each function that throws; the registry refuses it otherwise. fune verify --all runs each case in TypeScript, Python and Rust, and a project runs them again with fune verify. This page lists the cases; it does not run them. The exact JSON is vectors.json.

cidrInfo 15 tests

CaseArgumentsExpected
a /24 192.168.1.0/24 → cidr 192.168.1.0/24, network 192.168.1.0, prefix 24, netmask 255.255.255.0, wildcard 0.0.0.255, broadcast 192.168.1.255, first host 192.168.1.1, last host 192.168.1.254, host coun…
an interface address: host bits are dropped 192.168.1.77/24 → cidr 192.168.1.0/24, network 192.168.1.0, prefix 24, netmask 255.255.255.0, wildcard 0.0.0.255, broadcast 192.168.1.255, first host 192.168.1.1, last host 192.168.1.254, host coun…
a /8 10.0.0.0/8 → cidr 10.0.0.0/8, network 10.0.0.0, prefix 8, netmask 255.0.0.0, wildcard 0.255.255.255, broadcast 10.255.255.255, first host 10.0.0.1, last host 10.255.255.254, host count 16,777,…
a /12 that does not fall on an octet: 172.16-172.31 172.16.5.4/12 → cidr 172.16.0.0/12, network 172.16.0.0, prefix 12, netmask 255.240.0.0, wildcard 0.15.255.255, broadcast 172.31.255.255, first host 172.16.0.1, last host 172.31.255.254, host coun…
a /26 in the middle of a /24 203.0.113.64/26 → cidr 203.0.113.64/26, network 203.0.113.64, prefix 26, netmask 255.255.255.192, wildcard 0.0.0.63, broadcast 203.0.113.127, first host 203.0.113.65, last host 203.0.113.126, host …
a /30 has two hosts 192.168.1.0/30 → cidr 192.168.1.0/30, network 192.168.1.0, prefix 30, netmask 255.255.255.252, wildcard 0.0.0.3, broadcast 192.168.1.3, first host 192.168.1.1, last host 192.168.1.2, host count 2,…
a /31 point-to-point link: both addresses usable, no broadcast (RFC 3021) 198.51.100.7/31 → cidr 198.51.100.6/31, network 198.51.100.6, prefix 31, netmask 255.255.255.254, wildcard 0.0.0.1, broadcast —, first host 198.51.100.6, last host 198.51.100.7, host count 2, addre…
a /32 is one host 192.0.2.9/32 → cidr 192.0.2.9/32, network 192.0.2.9, prefix 32, netmask 255.255.255.255, wildcard 0.0.0.0, broadcast —, first host 192.0.2.9, last host 192.0.2.9, host count 1, address count 1
the whole IPv4 space 0.0.0.0/0 → cidr 0.0.0.0/0, network 0.0.0.0, prefix 0, netmask 0.0.0.0, wildcard 255.255.255.255, broadcast 255.255.255.255, first host 0.0.0.1, last host 255.255.255.254, host count 4,294,96…
prefix above 32 192.168.1.0/33 → error: is not a CIDR block
Show the other 5 tests
CaseArgumentsExpected
no prefix 192.168.1.0 → error: is not a CIDR block
a leading zero in the prefix 192.168.1.0/024 → error: is not a CIDR block
a trailing newline 192.168.1.0/24 → error: is not a CIDR block
a non-ASCII digit in the prefix 10.0.0.0/٨ → error: is not a CIDR block
IPv6 blocks are not described 2001:db8::/32 → error: cidrInfo handles IPv4 blocks only

cidrContains 18 tests

CaseArgumentsExpected
inside a /24 192.168.1.0/24, 192.168.1.200 → true
the next /24 is outside 192.168.1.0/24, 192.168.2.1 → false
the last address of a /8 10.0.0.0/8, 10.255.255.255 → true
172.31 is inside 172.16.0.0/12 172.16.0.0/12, 172.31.0.1 → true
172.32 is not (a naive /16 reading gets 172.16-only) 172.16.0.0/12, 172.32.0.1 → false
/0 contains everything of its family 0.0.0.0/0, 203.0.113.5 → true
/32 contains only itself 192.0.2.9/32, 192.0.2.10 → false
IPv6 inside a /32 2001:db8::/32, 2001:db8:ffff::1 → true
IPv6 just outside a /32 2001:db8::/32, 2001:db9::1 → false
link-local /10 reaches febf fe80::/10, febf::1 → true
Show the other 8 tests
CaseArgumentsExpected
link-local /10 stops before fec0 fe80::/10, fec0::1 → false
a /33 splits a group: 7fff is in the lower half 2001:db8::/33, 2001:db8:7fff::1 → true
a /33 splits a group: 8000 is in the upper half 2001:db8::/33, 2001:db8:8000::1 → false
an IPv4-mapped IPv6 address is not in an IPv4 block 10.0.0.0/8, ::ffff:10.0.0.1 → false
an IPv4 address is not in ::/0 ::/0, 10.0.0.1 → false
a malformed address 10.0.0.0/8, 10.0.0.256 → error: is not an IP address
a block without a prefix 10.0.0.0, 10.0.0.1 → error: is not a CIDR block
an IPv6 prefix above 128 2001:db8::/129, 2001:db8::1 → error: is not a CIDR block

isCidr 13 tests

CaseArgumentsExpected
an IPv4 block 10.0.0.0/8 → true
an IPv6 block 2001:db8::/32 → true
/0 0.0.0.0/0 → true
IPv6 /128 ::/128 → true
host bits set are still a block 192.168.1.77/24 → true
IPv4 prefix 33 10.0.0.0/33 → false
IPv6 prefix 129 ::/129 → false
a bare address 10.0.0.0 → false
two slashes 10.0.0.0/8/8 → false
a leading zero in the prefix 10.0.0.0/08 → false
Show the other 3 tests
CaseArgumentsExpected
a trailing newline 10.0.0.0/8 → false
a zone id fe80::1%eth0/64 → false
empty text → false

prefixToNetmask 12 tests

CaseArgumentsExpected
/24 24 → 255.255.255.0
/0 0 → 0.0.0.0
/8 8 → 255.0.0.0
/12 12 → 255.240.0.0
/20 20 → 255.255.240.0
/25 25 → 255.255.255.128
/30 30 → 255.255.255.252
/31 31 → 255.255.255.254
/32 32 → 255.255.255.255
33 is too long 33 → error: prefix must be an integer from 0 to 32
Show the other 2 tests
CaseArgumentsExpected
negative -1 → error: prefix must be an integer from 0 to 32
a fraction 24.5 → error: prefix must be an integer from 0 to 32

netmaskToPrefix 12 tests

CaseArgumentsExpected
255.255.255.0 is /24 255.255.255.0 → 24
all zeros is /0 0.0.0.0 → 0
all ones is /32 255.255.255.255 → 32
255.255.254.0 is /23 255.255.254.0 → 23
255.240.0.0 is /12 255.240.0.0 → 12
255.255.255.128 is /25 255.255.255.128 → 25
128.0.0.0 is /1 128.0.0.0 → 1
255.255.255.252 is /30 255.255.255.252 → 30
a gap in the one bits 255.0.255.0 → error: is not a contiguous netmask
a wildcard mask is not a netmask 0.255.255.255 → error: is not a contiguous netmask
Show the other 2 tests
CaseArgumentsExpected
a stray low bit 255.255.255.1 → error: is not a contiguous netmask
not a dotted quad 255.255.256.0 → error: is not a dotted-quad IPv4 address

More from the author

- **Host bits are allowed and dropped.** `192.168.1.77/24` is how an interface address is written, and it describes `192.168.1.0/24`; `cidrInfo` returns the cleaned-up block in `cidr`. (Python's `ipaddress.ip_network` refuses it unless `strict=False`; this behaves like `strict=False`.) - **/31 and /32.** A /31 is a point-to-point link: RFC 3021 makes both addresses usable, so `hostCount` is 2, the hosts are the two addresses and `broadcast` is null. A /32 is one host, also with no broadcast. Everything from /0 to /30 has network and broadcast addresses reserved, so `hostCount` is `addressCount - 2`. - **Families do not mix.** `cidrContains("10.0.0.0/8", "::ffff:10.0.0.1")` is false: an IPv4-mapped IPv6 address is a different address as far as a socket is concerned. Convert it first if you mean the IPv4 address. - **Strict text.** Addresses follow `net.ipv4` and `net.ipv6` (no leading zeros, no zone ids); the prefix is ASCII decimal with no leading zero, 0-32 for IPv4 and 0-128 for IPv6. - `cidrInfo` is IPv4 only: an IPv6 /64 has 2^64 addresses, which no language here holds in an `int`, and "broadcast" has no IPv6 meaning. - Netmasks must be contiguous: `255.0.255.0` is refused, and so is a wildcard mask such as `0.0.0.255` (write the netmask, `255.255.255.0`).

`cidrBlock` (`cidr_block`) is exported for the group's own functions; it is not part of the contract.

Sources: RFC 4632 (CIDR) section 3.1; RFC 3021 (Using 31-Bit Prefixes on IPv4 Point-to-Point Links); RFC 4291 section 2.3 (IPv6 prefix notation).

Files

PathBytes
README.md1,839
impl/python/cidr_contains.py1,080
impl/python/cidr_info.py1,358
impl/python/is_cidr.py1,224
impl/python/netmask_to_prefix.py427
impl/python/prefix_to_netmask.py405
impl/rust/cidr_contains.rs1,472
impl/rust/cidr_info.rs2,236
impl/rust/is_cidr.rs1,435
impl/rust/netmask_to_prefix.rs668
impl/rust/prefix_to_netmask.rs683
impl/typescript/cidr_contains.ts1,202
impl/typescript/cidr_info.ts1,453
impl/typescript/is_cidr.ts1,392
impl/typescript/netmask_to_prefix.ts461
impl/typescript/prefix_to_netmask.ts422
vectors.json9,910