function cidrv4PrefixLength
cidrv4PrefixLength(mask: Maskv4): PrefixLengthv4

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

Examples

Recovering prefix lengths from numbers

import { assertEquals } from "@std/assert";
import { cidrv4PrefixLength } from "@hertzg/ip/cidrv4";

assertEquals(cidrv4PrefixLength(0xFFFFFF00), 24);
assertEquals(cidrv4PrefixLength(0xFFFF0000), 16);
assertEquals(cidrv4PrefixLength(0xFF000000), 8);
assertEquals(cidrv4PrefixLength(0xFFFFFFFF), 32);
assertEquals(cidrv4PrefixLength(0), 0);

Parameters

mask: Maskv4

The network mask as a 32-bit unsigned integer

Return Type

The prefix length (0-32)

Throws

TypeError

If the mask's one bits are not contiguous from the top

RangeError

If the mask is not an integer in 0 to 0xFFFFFFFF

cidrv4PrefixLength(cidr: Cidrv4): PrefixLengthv4

Returns the prefix length of an IPv4 CIDR block.

A PrefixedCidrv4 gives back the prefix length it stores; a MaskedCidrv4 has its mask converted, which is where this can throw: a mask such as 255.0.255.0 describes no prefix length, so a block storing one has no answer here (ADR 0006).

Examples

Both dialects yield the same prefix length

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

assertEquals(cidrv4PrefixLength(parseCidrv4("192.168.1.0/24")), 24);
assertEquals(cidrv4PrefixLength({ address: 3232235776, mask: 0xFFFFFF00 }), 24);

A non-contiguous mask has no prefix length

import { assertThrows } from "@std/assert";
import { cidrv4PrefixLength } from "@hertzg/ip/cidrv4";

assertThrows(() => cidrv4PrefixLength({ address: 0, mask: 0xFF00FF00 }), TypeError);

Parameters

cidr: Cidrv4

The CIDR block

Return Type

The prefix length (0-32)

Throws

TypeError

If a masked block's mask is not contiguous

RangeError

If a masked block's mask is not a 32-bit unsigned integer

cidrv4PrefixLength(mask: string): PrefixLengthv4

Recovers the prefix length from an IPv4 network mask given in dotted decimal notation.

The string is parsed with the same rules as parseAddressv4 -- four octets, each 0-255, no leading zeros -- and then interpreted as a mask rather than an address.

Examples

Recovering prefix lengths from dotted decimal

import { assertEquals } from "@std/assert";
import { cidrv4PrefixLength } from "@hertzg/ip/cidrv4";

assertEquals(cidrv4PrefixLength("255.255.255.0"), 24);
assertEquals(cidrv4PrefixLength("255.255.0.0"), 16);
assertEquals(cidrv4PrefixLength("255.255.255.252"), 30);
assertEquals(cidrv4PrefixLength("0.0.0.0"), 0);
assertEquals(cidrv4PrefixLength("255.255.255.255"), 32);

Building a CIDR from an interface netmask

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

const { address, netmask } = { address: "192.168.1.42", netmask: "255.255.255.0" };

assertEquals(
  stringifyCidrv4({
    address: parseAddressv4(address).address,
    prefixLength: cidrv4PrefixLength(netmask),
  }),
  "192.168.1.42/24",
);

Parameters

mask: string

The network mask in dotted decimal notation (e.g. "255.255.255.0")

Return Type

The prefix length (0-32)

Throws

TypeError

If the notation is malformed, or the mask's one bits are not contiguous from the top

RangeError

If any octet is out of range (not 0-255)

cidrv4PrefixLength(cidrOrMask: Cidrv4 | Maskv4 | string): PrefixLengthv4

Recovers the prefix length from an IPv4 CIDR block or network mask.

The inverse of cidrv4Mask. Accepts a Cidrv4 in either dialect, a 32-bit unsigned integer, or dotted decimal notation.

A CIDR mask is a run of one bits from the most significant end followed by zeros; masks that do not have that shape (0xFF00FF00, "255.0.255.0") describe no prefix length at all and are rejected rather than answered with a plausible-looking count of set bits. This is the one place a stored mask is checked, because it is the one call that has no answer for it (ADR 0006).

Examples

Both forms agree

import { assertEquals } from "@std/assert";
import { cidrv4PrefixLength } from "@hertzg/ip/cidrv4";

assertEquals(cidrv4PrefixLength("255.255.255.0"), 24);
assertEquals(cidrv4PrefixLength(0xFFFFFF00), 24);

Non-contiguous masks throw, in either form

import { assertThrows } from "@std/assert";
import { cidrv4PrefixLength } from "@hertzg/ip/cidrv4";

assertThrows(() => cidrv4PrefixLength(0xFF00FF00), TypeError);
assertThrows(() => cidrv4PrefixLength("255.0.255.0"), TypeError);
assertThrows(() => cidrv4PrefixLength("0.0.0.255"), TypeError);

Round-trips with cidrv4Mask

import { assertEquals } from "@std/assert";
import { cidrv4Mask, cidrv4PrefixLength } from "@hertzg/ip/cidrv4";

for (let prefixLength = 0; prefixLength <= 32; prefixLength++) {
  assertEquals(cidrv4PrefixLength(cidrv4Mask(prefixLength)), prefixLength);
}

Error handling

import { assertThrows } from "@std/assert";
import { cidrv4PrefixLength } from "@hertzg/ip/cidrv4";

// Wrong shape -- in range, but not a mask
assertThrows(() => cidrv4PrefixLength(0xFF00FF00), TypeError);
assertThrows(() => cidrv4PrefixLength("255.0.255.0"), TypeError);

// Malformed notation
assertThrows(() => cidrv4PrefixLength("255.255.255"), TypeError);
assertThrows(() => cidrv4PrefixLength("255.255.255.256"), RangeError);

// Wrong range -- not a 32-bit unsigned integer at all
assertThrows(() => cidrv4PrefixLength(-1), RangeError);
assertThrows(() => cidrv4PrefixLength(0x100000000), RangeError);
assertThrows(() => cidrv4PrefixLength(1.5), RangeError);

Parameters

cidrOrMask: Cidrv4 | Maskv4 | string

A Cidrv4 block, or the network mask as a 32-bit unsigned integer or dotted decimal

Return Type

The prefix length (0-32)

Throws

TypeError

If the mask is not contiguous, or the notation is malformed

RangeError

If the mask is out of range