Ethernet II frame encoding and decoding.
A frame is a 6-byte destination MAC, a 6-byte source MAC, a 2-byte EtherType, and a variable-length payload:
0 7 8 15 16 23 24 31 +--------+--------+--------+--------+ | Destination MAC (4 of 6) | +--------+--------+--------+--------+ | DstMAC (last 2) | SrcMAC (1st 2) | +--------+--------+--------+--------+ | Source MAC (4 of 6) | +--------+--------+--------+--------+ | EtherType | | +-----------------+ Payload | | (variable) | +-----------------------------------+
The frame check sequence (FCS) at the end of a wire frame is not part of this coder's layout — kernels and NICs handle it.
For MAC address parsing/stringification, use the sister package @hertzg/mac.
Migration from 0.x
The parseMacAddress and stringifyMacAddress exports were removed in
1.0. Replace with @hertzg/mac:
// before import { parseMacAddress, stringifyMacAddress } from "@binstruct/ethernet"; // after import { parse as parseMac, stringify as stringifyMac } from "@hertzg/mac";
Basic encoding and decoding
Basic encoding and decoding
import { assertEquals } from "@std/assert"; import { ethernet2Frame } from "@binstruct/ethernet"; const frameCoder = ethernet2Frame(); const testFrame = { dstMac: new Uint8Array([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]), srcMac: new Uint8Array([0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB]), etherType: 0x0800, // IPv4 payload: new Uint8Array([0x45, 0x00, 0x00, 0x14]), }; const buffer = new Uint8Array(1500); const bytesWritten = frameCoder.encode(testFrame, buffer); const [decodedFrame, bytesRead] = frameCoder.decode(buffer); assertEquals(bytesRead, buffer.length); assertEquals(bytesWritten, 18); assertEquals(decodedFrame.dstMac, testFrame.dstMac); assertEquals(decodedFrame.srcMac, testFrame.srcMac); assertEquals(decodedFrame.etherType, testFrame.etherType);
Compose with @hertzg/mac for string-form addresses
Compose with @hertzg/mac for string-form addresses
import { assertEquals } from "@std/assert"; import { refine } from "@hertzg/binstruct"; import { ethernet2Frame, type Ethernet2Frame } from "@binstruct/ethernet"; import { parse as parseMac, stringify as stringifyMac } from "@hertzg/mac"; type StringMacFrame = Omit<Ethernet2Frame, "dstMac" | "srcMac"> & { dstMac: string; srcMac: string; }; const frameCoder = refine(ethernet2Frame(), { refine: (frame: Ethernet2Frame): StringMacFrame => ({ ...frame, dstMac: stringifyMac(frame.dstMac), srcMac: stringifyMac(frame.srcMac), }), unrefine: (frame: StringMacFrame): Ethernet2Frame => ({ ...frame, dstMac: parseMac(frame.dstMac), srcMac: parseMac(frame.srcMac), }), })(); const buffer = new Uint8Array(1500); frameCoder.encode({ dstMac: "00:11:22:33:44:55", srcMac: "66:77:88:99:aa:bb", etherType: 0x0800, payload: new Uint8Array([0x45, 0x00, 0x00, 0x14]), }, buffer); const [decoded] = frameCoder.decode(buffer); assertEquals(decoded.dstMac, "00:11:22:33:44:55");