# ByteWriter _(no submodules)_ ## Purpose Provides a dynamic binary writer for building TIFF/EXIF byte streams from scratch. It maintains an auto-growing `Uint8Array` buffer and exposes typed write methods for all TIFF primitive types. This is the write-side counterpart to `ByteReader`, sharing the same byte-order model and error infrastructure. ## Features - Auto-growing buffer (doubles capacity on overflow, no pre-allocation required) - Big-endian and little-endian support with runtime `setByteOrder()` switching - Full TIFF primitive coverage: uint8/16/32, int16, rational, raw bytes, strings - Fluent API — all write methods return `this` for chaining - `toUint8Array()` snapshot of the written bytes at any point - `ExifError` with `EXIF.WRITE_ERROR` on non-Latin-1 string characters ## Usage: Basic Example ```ts import { ByteWriter } from "@suaveplan/exif/binary"; const writer = new ByteWriter(64, "BE"); writer.writeUint16(0x4D4D); // big-endian BOM writer.writeUint16(0x002A); // TIFF magic writer.writeUint32(8); // IFD0 offset const bytes = writer.toUint8Array(); // Uint8Array [ 0x4D, 0x4D, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x08 ] ``` ## Usage: Advanced Example ```ts import { ByteWriter } from "@suaveplan/exif/binary"; // Fluent chaining const exifHeader = new ByteWriter() .setByteOrder("LE") .writeBytes(new Uint8Array([0x45, 0x78, 0x69, 0x66, 0x00, 0x00])) // "Exif\0\0" .writeUint16(0x4949) // LE BOM .writeUint16(0x002A) .writeUint32(8) .toUint8Array(); // Writing a RATIONAL (e.g. exposure time 1/100) const writer = new ByteWriter(); writer.writeRational({ numerator: 1, denominator: 100 }); ``` ## API Reference ### `constructor(initialSize?: number, byteOrder?: ByteOrder): ByteWriter` Creates a new writer. `initialSize` defaults to 256 bytes. `byteOrder` defaults to `"BE"`. ### `get position: number` Returns the current write cursor position (total bytes written so far). ### `setByteOrder(order: ByteOrder): this` Switches the active byte order. Returns `this` for chaining. ### `writeUint8(value: number): this` Writes one unsigned byte. ### `writeUint16(value: number): this` Writes a 2-byte unsigned integer using the active byte order. ### `writeUint32(value: number): this` Writes a 4-byte unsigned integer using the active byte order. ### `writeInt16(value: number): this` Writes a 2-byte signed integer using the active byte order. ### `writeBytes(bytes: Uint8Array): this` Appends a raw byte array. ### `writeString(str: string): this` Writes a Latin-1 string without null termination. Throws `ExifError(WRITE_ERROR)` if any character is outside the Latin-1 range (> U+00FF). ### `writeRational(r: Rational): this` Writes an 8-byte TIFF RATIONAL (two unsigned 32-bit integers: numerator then denominator). ### `toUint8Array(): Uint8Array` Returns a copy of all bytes written so far (from position 0 to the current cursor). ## Implementation Notes The buffer starts at `initialSize` and doubles whenever the next write would overflow. This amortizes allocation cost to O(log n) reallocations for n total bytes written. The `view` is recreated after each reallocation since `DataView` binds to a specific `ArrayBuffer` instance. `toUint8Array()` always returns a fresh slice to prevent the caller from holding a reference to the internal buffer.