{"id":12717,"library":"buffer-layout","title":"Buffer Layout","description":"buffer-layout is a pure JavaScript utility library designed for translating between JavaScript values and Node.js Buffers. It enables developers to define and manipulate binary data structures that closely mimic C structs, offering explicit control over memory layout and endianness. The library provides layout constructors for various data types, including signed and unsigned integers (1 to 6 bytes, with 64-bit integers decoded as standard JavaScript Numbers), floats, doubles, sequences, complex structures, unions, bit fields, NUL-terminated C strings, and raw data blobs. The current version, 1.2.2, was last published in 2021. Given its age and lack of recent updates on its GitHub repository (last commit approximately four years ago), the project appears to be in an abandoned state, with no active development or maintenance. A key differentiator is its detailed control over C-style memory layouts, including the necessity of manually accounting for padding and bit fields.","status":"abandoned","version":"1.2.2","language":"javascript","source_language":"en","source_url":"https://github.com/pabigot/buffer-layout","tags":["javascript","Buffer","struct","endian","pack data"],"install":[{"cmd":"npm install buffer-layout","lang":"bash","label":"npm"},{"cmd":"yarn add buffer-layout","lang":"bash","label":"yarn"},{"cmd":"pnpm add buffer-layout","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"This package is primarily CommonJS. Direct ESM import (`import lo from 'buffer-layout';`) will fail in a native ESM environment without a CommonJS wrapper or bundler. Named imports like `import { struct } from 'buffer-layout'` are not supported.","wrong":"import lo from 'buffer-layout';","symbol":"buffer-layout","correct":"const lo = require('buffer-layout');"},{"note":"Layout constructors like `struct` are properties of the default export. Destructuring from `require` is common for convenience, or they are accessed via the `lo` alias (e.g., `lo.struct`).","wrong":"import { struct } from 'buffer-layout';","symbol":"lo.struct","correct":"const { struct } = require('buffer-layout'); // or lo.struct"},{"note":"Similar to `lo.struct`, `u8` (unsigned 8-bit integer) is a method available on the module's default export. Named ESM imports for these methods are incorrect.","wrong":"import { u8 } from 'buffer-layout';","symbol":"lo.u8","correct":"const { u8 } = require('buffer-layout'); // or lo.u8"}],"quickstart":{"code":"const assert = require('assert');\nconst lo = require('buffer-layout');\n\n// Define a C-like packed struct without padding\n// C: struct { uint8_t a; uint16_t b; } __attribute__((__packed__)) MyPackedStruct;\nconst packedStruct = lo.struct([\n  lo.u8('a'),\n  lo.u16le('b') // u16le for unsigned 16-bit little-endian\n]);\n\nconst packedBuffer = Buffer.alloc(3); // 1 byte for 'a', 2 bytes for 'b'\nconst data1 = { a: 0x12, b: 0x3456 };\npackedStruct.encode(data1, packedBuffer);\n\nconsole.log('Packed Buffer:', packedBuffer.toString('hex'));\nassert.equal(packedBuffer.toString('hex'), '125634');\nassert.deepStrictEqual(packedStruct.decode(packedBuffer), data1);\n\n// Define a C-like struct WITH padding, simulating a 32-bit aligned machine\n// C: struct { uint8_t v; uint32_t u32; } MyAlignedStruct;\n// In C, u32 would typically be 4-byte aligned, causing 3 bytes of padding after u8.\nconst alignedStruct = lo.struct([\n  lo.u8('v'),\n  lo.seq(lo.u8(), 3, 'padding'), // explicit padding for 4-byte alignment\n  lo.u32le('u32')\n]);\n\nconst alignedBuffer = Buffer.alloc(8); // 1 byte (v) + 3 bytes (padding) + 4 bytes (u32)\nalignedBuffer.fill(0xBD); // Fill with a recognizable pattern for padding\nconst data2 = { v: 0x01, u32: 0x12345678 };\nalignedStruct.encode(data2, alignedBuffer);\n\nconsole.log('Aligned Buffer (with padding):', alignedBuffer.toString('hex'));\nassert.equal(alignedBuffer.toString('hex'), '01bdbdbd78563412');\nassert.deepStrictEqual(alignedStruct.decode(alignedBuffer), { v: 1, u32: 0x12345678 });\n\nconsole.log('Quickstart examples completed successfully.');","lang":"javascript","description":"Demonstrates defining both packed and aligned C-style structs using `buffer-layout`, showing how to encode JavaScript objects into Buffers and decode them back, including explicit padding for alignment."},"warnings":[{"fix":"Consider migrating to a maintained alternative like `@solana/buffer-layout` which is a TypeScript-enabled fork with active maintenance and similar API.","message":"The `buffer-layout` package is currently abandoned. There will be no further updates, bug fixes, or security patches, which could lead to compatibility issues with newer Node.js versions or unaddressed vulnerabilities.","severity":"breaking","affected_versions":">=1.2.2"},{"fix":"Use `lo.seq(lo.u8(), N)` or `lo.blob(N)` with no property name to insert `N` bytes of padding where required by alignment rules of the target C structure.","message":"When defining structures that mimic C `struct`s, developers must manually account for memory alignment and add explicit padding layouts. Failing to do so will result in incorrect buffer sizes, offsets, and ultimately corrupted data during encoding and decoding.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For precise handling of 64-bit integers, use layouts that return `BigInt` (if available in a fork/alternative) or implement manual conversion using `BigInt` after decoding the raw bytes. The original `buffer-layout` library does not natively support `BigInt`.","message":"64-bit integral values (e.g., `lo.u64`, `lo.s64`) are decoded into standard JavaScript `Number` types. Due to JavaScript's floating-point number representation (IEEE 754 double-precision), integers larger than 2^53 - 1 (or smaller than -2^53 + 1) cannot be precisely represented, leading to potential data loss or approximation.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Install `@types/buffer-layout` if available, or consider migrating to `@solana/buffer-layout`, which is a TypeScript-first fork and provides native types.","message":"The package does not ship with its own TypeScript declaration files. While community-maintained `@types/buffer-layout` might exist, their reliability and up-to-dateness can vary. This leads to a suboptimal developer experience in TypeScript projects.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure you are using CommonJS `const lo = require('buffer-layout');` in a CJS file, or configure your bundler to handle CJS modules in an ESM project. If using native ESM, you might need to use `import * as lo from 'buffer-layout';` or ensure your `package.json` specifies `\"type\": \"commonjs\"` for the file.","cause":"Attempting to `require('buffer-layout')` in an ES Module context, or `import`ing `buffer-layout` directly in a CommonJS context.","error":"TypeError: require is not a function"},{"fix":"Review your layout definition against the target binary format or C struct definition. Pay close attention to data types, endianness, and explicit padding needed for memory alignment. Use `Buffer.compare` or `Buffer.equals` for byte-by-byte comparison during debugging.","cause":"Often occurs when `encode` or `decode` operations produce unexpected results, frequently due to incorrect layout definitions, especially missing padding for C-style structs.","error":"AssertionError: Buffers not equal"},{"fix":"Verify that the `Buffer.alloc()` size is sufficient for the defined layout (`layout.span`). Double-check any manual offset parameters passed to `encode` or `decode` methods.","cause":"Trying to encode or decode data beyond the allocated size of the `Buffer`, or specifying an incorrect offset during read/write operations within `buffer-layout` methods.","error":"RangeError: offset is out of bounds"}],"ecosystem":"npm"}