function addressFromBytes
addressFromBytes(bytes: Uint8Array): Address

Reads an IPv4 or IPv6 address from a buffer, picking the version from its length.

bytes must be exactly 4 bytes (read as IPv4, returning number) or exactly 16 (read as IPv6, returning bigint). Any other length throws a RangeError rather than guessing.

There is deliberately no offset parameter. An offset would make the width depend on how much data happens to trail the field rather than on the caller's intent — a 4-byte address 8 bytes from the end of a frame would read as IPv4, and the same field in the same position would read as IPv6 the day the frame grew. Pass the exact bytes instead, with packet.subarray(12, 16), which is a non-copying view; or, when the version is already known, use addressv4FromBytes or addressv6FromBytes, which do take an offset because their width comes from the function rather than from the buffer.

Unlike parseAddress, this does not unwrap IPv4-mapped addresses. Sixteen bytes always return a bigint, so that addressToBytes(addressFromBytes(b)).length === b.length. Callers wanting the dual-stack normalization compose unmapToAddressv4 explicitly.

Examples

The length picks the version

import { assertEquals } from "@std/assert";
import { addressFromBytes } from "@hertzg/ip/bytes";
import { stringifyAddress } from "@hertzg/ip/address";

assertEquals(stringifyAddress(addressFromBytes(new Uint8Array([10, 0, 0, 1]))), "10.0.0.1");
assertEquals(stringifyAddress(addressFromBytes(new Uint8Array(16))), "::");

Sixteen mapped bytes stay IPv6

import { assertEquals } from "@std/assert";
import { addressFromBytes, addressToBytes } from "@hertzg/ip/bytes";
import { unmapToAddressv4 } from "@hertzg/ip/addressv6";
import { stringifyAddressv4 } from "@hertzg/ip/addressv4";

// deno-fmt-ignore
const mapped = new Uint8Array([
  0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0xff, 0xff, 192, 168, 1, 1,
]);

const address = addressFromBytes(mapped);
assertEquals(typeof address, "bigint");
assertEquals(addressToBytes(address).length, 16);

// Normalizing to IPv4 is an explicit, separate step
assertEquals(stringifyAddressv4(unmapToAddressv4(address as bigint)), "192.168.1.1");

Any other length throws instead of guessing

import { assertThrows } from "@std/assert";
import { addressFromBytes } from "@hertzg/ip/bytes";

assertThrows(() => addressFromBytes(new Uint8Array(20)), RangeError);
assertThrows(() => addressFromBytes(new Uint8Array(6)), RangeError);

Reading a field out of a frame, by slicing rather than offsetting

import { assertEquals } from "@std/assert";
import { addressFromBytes } from "@hertzg/ip/bytes";
import { addressv4FromBytes } from "@hertzg/ip/bytesv4";
import { stringifyAddress } from "@hertzg/ip/address";

// deno-fmt-ignore
const packet = new Uint8Array([
  0x45, 0x00, 0x00, 0x54, 0x1c, 0x46, 0x40, 0x00,
  0x40, 0x06, 0x00, 0x00,
  10, 0, 0, 1,
  192, 168, 1, 1,
]);

// `subarray` is a view, not a copy, and it states the width
assertEquals(stringifyAddress(addressFromBytes(packet.subarray(12, 16))), "10.0.0.1");

// When the version is known, the version-specific function takes the offset
assertEquals(addressv4FromBytes(packet, 12), addressFromBytes(packet.subarray(12, 16)));

Parameters

The buffer to read, which must be exactly 4 or 16 bytes long

Return Type

The address as number (IPv4) or bigint (IPv6)

Throws

RangeError

If bytes is neither 4 nor 16 bytes long