function parseCidr
parseCidr(
cidr: string,
options?: ParseOptions
): ParsedCidr

Parses IPv4 or IPv6 CIDR notation, in either dialect and with an optional zone ID.

Detects the IP version from the address slot -- a : means IPv6, otherwise IPv4 -- and hands the string to parseCidrv6 or parseCidrv4, so the accepted grammar is exactly theirs: an address, an optional %zoneId carried verbatim, then / and a prefix length or a mask of the same version.

An IPv4-mapped IPv6 block is unmapped to an IPv4 block by default (ADR 0004), but only when the whole ::ffff:0:0/96 prefix is fixed: a prefix length of 96 or longer, or a mask whose high 96 bits are all ones. The dialect is kept, the prefix length is reduced by 96 and a mask keeps its low 32 bits, so ::ffff:192.168.1.0/120 becomes 192.168.1.0/24. ::ffff:1.2.3.4/64 is an IPv6 block that happens to start in the mapped range and stays IPv6. Pass { unmapToV4: false } to keep every IPv6 block, or use parseCidrv6, which never unmaps. The zone ID, if any, is carried either way.

Examples

Both versions and both dialects

import { assertEquals } from "@std/assert";
import { parseCidr } from "@hertzg/ip/cidr";

assertEquals(parseCidr("10.0.0.0/8"), { address: 167772160, prefixLength: 8 });
assertEquals(parseCidr("10.0.0.0/255.0.0.0"), { address: 167772160, mask: 0xFF000000 });
assertEquals(parseCidr("fe80::/10"), { address: 0xfe80n << 112n, prefixLength: 10 });
assertEquals(parseCidr("fe80::%ether1/64"), { address: 0xfe80n << 112n, prefixLength: 64, zoneId: "ether1" });

IPv4-mapped blocks unmap at /96 or longer

import { assertEquals } from "@std/assert";
import { parseCidr } from "@hertzg/ip/cidr";

assertEquals(parseCidr("::ffff:192.168.1.0/120"), { address: 3232235776, prefixLength: 24 });
assertEquals(parseCidr("::ffff:192.168.1.0/96"), { address: 3232235776, prefixLength: 0 });
assertEquals(
  parseCidr("::ffff:192.168.1.0/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"),
  { address: 3232235776, mask: 0xFFFFFF00 },
);
assertEquals(parseCidr("::ffff:192.168.1.0/64"), { address: 0xffffc0a80100n, prefixLength: 64 });
assertEquals(
  parseCidr("::ffff:192.168.1.0/120", { unmapToV4: false }),
  { address: 0xffffc0a80100n, prefixLength: 120 },
);

An address alone is not a CIDR block

import { assertThrows } from "@std/assert";
import { parseCidr } from "@hertzg/ip/cidr";

assertThrows(() => parseCidr("10.0.0.1"), TypeError);
assertThrows(() => parseCidr("fe80::1%eth0"), TypeError);

Parameters

cidr: string

The CIDR notation string, e.g. "192.168.1.0/24", "2001:db8::/32", "fe80::%ether1/64", "10.0.0.0/255.0.0.0"

optional
options: ParseOptions

unmapToV4, default true

Return Type

The parsed CIDR as a ParsedCidrv4 or ParsedCidrv6

Throws

TypeError

If the format is invalid, including a missing prefix and a mask of the other version

RangeError

If a well-formed number is out of range