IPv4 CIDR notation parsing and utilities.

This module provides CIDR parsing, network calculations, and IP range checking for IPv4 networks. Works with number representations to enable efficient IP assignment workflows.

A Cidrv4 stores whichever dialect it was written in, a prefix length (10.0.0.0/8) or a network mask (10.0.0.0/255.0.0.0), and every operation here accepts both.

Examples

Both dialects parse, and write back the way they came

import { assertEquals } from "@std/assert";
import { cidrv4Size, parseCidrv4, stringifyCidrv4 } from "@hertzg/ip/cidrv4";

const prefixed = parseCidrv4("10.0.0.0/8");
const masked = parseCidrv4("10.0.0.0/255.0.0.0");

assertEquals(cidrv4Size(prefixed), cidrv4Size(masked));
assertEquals(stringifyCidrv4(prefixed), "10.0.0.0/8");
assertEquals(stringifyCidrv4(masked), "10.0.0.0/255.0.0.0");

CIDR operations

import { assert, assertEquals } from "@std/assert";
import { cidrv4Contains, parseCidrv4 } from "@hertzg/ip/cidrv4";
import { parseAddressv4 } from "@hertzg/ip/addressv4";

const cidr = parseCidrv4("192.168.1.0/24");

assert(cidrv4Contains(cidr, parseAddressv4("192.168.1.1").address));
assertEquals(cidrv4Contains(cidr, parseAddressv4("192.168.2.1").address), false);

Handing out assignable addresses

import { assertEquals } from "@std/assert";
import {
  cidrv4UsableAddresses,
  cidrv4UsableSize,
  parseCidrv4,
} from "@hertzg/ip/cidrv4";
import { stringifyAddressv4 } from "@hertzg/ip/addressv4";

const pool = parseCidrv4("192.168.1.0/24");
const assigned = Array.from(cidrv4UsableAddresses(pool), stringifyAddressv4);

assertEquals(assigned.length, cidrv4UsableSize(pool));
assertEquals(assigned[0], "192.168.1.1");
assertEquals(assigned.at(-1), "192.168.1.254");

Functions

f
cidrv4BroadcastAddress(cidr: Cidrv4): number

Returns the directed broadcast address of a CIDR block.

f
cidrv4Contains(
cidr: Cidrv4,
address: number
): boolean

Checks if an IPv4 address is contained within a CIDR block.

f
cidrv4ContainsCidr(
outer: Cidrv4,
inner: Cidrv4
): boolean

Checks if one IPv4 CIDR block fully contains another.

f
cidrv4FirstAddress(cidr: Cidrv4): number

Returns the first address of a CIDR block (network address).

f
cidrv4FirstUsableAddress(cidr: Cidrv4): number

Returns the first assignable address of a CIDR block.

f
cidrv4Intersect(
a: Cidrv4,
b: Cidrv4
): Cidrv4 | null

Returns the intersection of two IPv4 CIDR blocks.

f
cidrv4LastAddress(cidr: Cidrv4): number

Returns the last address of a CIDR block (broadcast address for IPv4).

f
cidrv4LastUsableAddress(cidr: Cidrv4): number

Returns the last assignable address of a CIDR block.

f
cidrv4Mask(cidrOrPrefixLength: Cidrv4 | PrefixLengthv4): Maskv4
3 overloads

Creates a network mask from an IPv4 prefix length.

f
cidrv4Merge(cidrs: readonly Cidrv4[]): Cidrv4[]

Merges IPv4 CIDR blocks into the minimal covering set.

f
cidrv4NetworkAddress(cidr: Cidrv4): number

Returns the network address of a CIDR block.

f
cidrv4Overlaps(
a: Cidrv4,
b: Cidrv4
): boolean

Checks if two IPv4 CIDR blocks overlap (share at least one address).

f
cidrv4PrefixLength(cidrOrMask: Cidrv4 | Maskv4 | string): PrefixLengthv4
4 overloads

Recovers the prefix length from an IPv4 network mask given as a 32-bit unsigned integer.

f
cidrv4Size(cidrOrPrefixLength: Cidrv4 | PrefixLengthv4): number
3 overloads

Returns the total number of IP addresses in a CIDR block.

f
cidrv4Subtract(
a: Cidrv4,
b: Cidrv4
): Cidrv4[]

Subtracts one IPv4 CIDR block from another.

f
cidrv4UsableAddresses(cidr: Cidrv4): Generator<number>

Generates every assignable address in a CIDR block, in ascending order.

f
cidrv4UsableSize(cidrOrPrefixLength: Cidrv4 | PrefixLengthv4): number
3 overloads

Returns the number of assignable addresses in a CIDR block.

f
compareCidrv4(
a: Cidrv4,
b: Cidrv4
): -1 | 0 | 1

Compares two IPv4 CIDR blocks for sorting.

f
parseCidrv4(cidr: string): ParsedCidrv4

Parses IPv4 CIDR notation, in either dialect and with an optional zone ID, to a ParsedCidrv4.

f
stringifyCidrv4(cidr: Addressv4 | ParsedAddressv4 | ParsedCidrv4): string

Stringifies an IPv4 CIDR block, or an address, to CIDR notation.

Type Aliases

T
Addressv4 = number

An IPv4 address as a 32-bit unsigned integer, 0 to 4294967295. The primitive type is what carries the version: a number is IPv4, a bigint is IPv6 (ADR 0001).

T
Cidrv4 = PrefixedCidrv4 | MaskedCidrv4

Represents an IPv4 CIDR block.

T
MaskedCidrv4 = { readonly address: Addressv4; readonly mask: Maskv4; readonly prefixLength?: never; }

An IPv4 CIDR block written with a network mask, as in 10.0.0.0/255.0.0.0.

T
Maskv4 = number

An IPv4 network mask as a 32-bit unsigned integer, e.g. 0xFFFFFF00 for /24.

T
ParsedAddressv4 = { readonly address: Addressv4; readonly zoneId?: ZoneId; }

What parseAddressv4 returns and what stringifyAddressv4 accepts: the address, plus the zone ID if the notation had one. Read .address for the bare Addressv4; the zone never touches the value, and no operation in this package reads it.

T
ParsedCidrv4 = Cidrv4 & { readonly zoneId?: ZoneId; }

What parseCidrv4 returns and what stringifyCidrv4 accepts: a Cidrv4 in the dialect it was written in, plus the zone ID if the notation had one (fe80::%ether1/64 has one; RouterOS emits that form for connected routes). Assignable to Cidrv4, so a parse result goes straight into every cidrv4* operation; none of them reads the zone.

T
PrefixedCidrv4 = { readonly address: Addressv4; readonly prefixLength: PrefixLengthv4; readonly mask?: never; }

An IPv4 CIDR block written with a prefix length, as in 10.0.0.0/8.

T
PrefixLengthv4 = number

An IPv4 prefix length, the 24 in /24. The range is 0 to 32; it is documented rather than encoded in the type, so prefixLength + 1 stays a PrefixLengthv4 (ADR 0002).

T
ZoneId = string

The zone ID of an address, the interface tail after % in fe80::1%eth0 (RFC 4007 section 11). Carried verbatim by the Parsed* types; never percent-decoded, so %25eth0 is the zone 25eth0.