function compareAddress
compareAddress(): -1 | 0 | 1

Compares two IP addresses of either version for sorting.

The order is version-first and total: every IPv4 address (number) sorts before every IPv6 address (bigint), and within a version addresses sort numerically ascending. Mixed-version arguments are not an error — unlike the universal CIDR operations, this function never throws, because sorting a mixed dual-stack list is the reason it exists. Go's net/netip, Rust's std::net::IpAddr and PostgreSQL's inet all order addresses the same way.

Note that "IPv4 sorts first" is a statement about order, not about magnitude: the two address spaces are disjoint and nothing is converted between them. An IPv4-mapped address held as a bigint is an IPv6 value and sorts in the IPv6 half — see the example below. In practice parseAddress already unwraps mapped addresses to their IPv4 number form, so a mapped bigint only reaches this function via parseAddressv6.

Examples

Sort a mixed dual-stack list, ascending or descending

import { assertEquals } from "@std/assert";
import { compareAddress, parseAddress, stringifyAddress } from "@hertzg/ip/address";

const clients = ["2001:db8::1", "10.0.0.2", "::1", "10.0.0.1"].map((s) => parseAddress(s).address);

assertEquals(clients.toSorted(compareAddress).map(stringifyAddress), [
  "10.0.0.1",
  "10.0.0.2",
  "::1",
  "2001:db8::1",
]);

// Descending: swap the arguments
assertEquals(clients.toSorted((a, b) => compareAddress(b, a)).map(stringifyAddress), [
  "2001:db8::1",
  "::1",
  "10.0.0.2",
  "10.0.0.1",
]);

Every IPv4 address sorts before every IPv6 address

import { assertEquals } from "@std/assert";
import { compareAddress, parseAddress } from "@hertzg/ip/address";

assertEquals(compareAddress(parseAddress("255.255.255.255").address, parseAddress("::").address), -1);
assertEquals(compareAddress(parseAddress("::").address, parseAddress("0.0.0.0").address), 1);

An IPv4-mapped bigint is an IPv6 value, not its IPv4 twin

import { assertEquals } from "@std/assert";
import { compareAddress } from "@hertzg/ip/address";
import { parseAddressv4 } from "@hertzg/ip/addressv4";
import { parseAddressv6 } from "@hertzg/ip/addressv6";

const mapped = parseAddressv6("::ffff:10.0.0.1").address;
const plain = parseAddressv4("10.0.0.1").address;

assertEquals(compareAddress(mapped, plain), 1);

Parameters

The first address

The second address

Return Type

-1 | 0 | 1

-1 if a sorts before b, 1 if after, 0 if equal