Skip to content

About

zig binarystream

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Latest commit

 

History

11 Commits

Folders and files

Repository files navigation

zig-binarystream

Zig 0.16.0 CI

A small, dependency-free binary reader/writer for Zig. It is designed for binary protocols, packet construction, file formats, and lightweight serialization.

The current release targets the latest stable Zig release, Zig 0.16.0.

Features

  • Bounds-checked reads with error.EndOfStream instead of slicing panics
  • Explicit little- or big-endian generic integer I/O
  • Little-endian compatibility helpers for the original API
  • Checked 7-bit encoded integers, including malformed-input detection
  • 7-bit and u8 length-prefixed strings
  • Transactional compound reads: a failed string or VarInt read restores the cursor
  • Reusable allocation with reset and clear operations
  • No dependencies outside the Zig standard library

Installation

Add the package to your project:

zig fetch --save=binarystream https://github.com/itzmiadm/zig-binarystream/archive/refs/heads/main.tar.gz

Expose its module from your build.zig:

const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const app = b.addExecutable(.{
    .name = "app",
    .root_module = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    }),
});

const binarystream = b.dependency("binarystream", .{
    .target = target,
    .optimize = optimize,
});
app.root_module.addImport("binarystream", binarystream.module("binarystream"));

Then import it in Zig:

const BinaryStream = @import("binarystream").BinaryStream;

Example

const std = @import("std");
const BinaryStream = @import("binarystream").BinaryStream;

pub fn main(init: std.process.Init) !void {
    var stream = BinaryStream.init(init.arena.allocator());
    defer stream.deinit();

    try stream.writeByte(7);
    try stream.writeInt(u32, 0x12345678, .big);
    try stream.writeString("hello");

    stream.resetReader();
    const message_type = try stream.readByte();
    const request_id = try stream.readInt(u32, .big);
    const payload = try stream.readString();

    std.debug.print("type={d} id={x} payload={s}\n", .{
        message_type,
        request_id,
        payload,
    });
}

API overview

Area Methods
Lifecycle init, initCapacity, initFromSlice, deinit
Buffer bytes, write, read, skip
Cursor position, remaining, setPosition, resetReader
Integers writeInt, readInt, writeByte, readByte
Strings writeString, readString, writeString8, readString8
VarInts write7BitEncodedInt, read7BitEncodedInt
Reuse clearRetainingCapacity

writeInt and readInt require an explicit .little or .big byte order. The compatibility methods writeU16, writeInt16, writeInt32, writeU64, and their read counterparts use little-endian encoding on every platform.

Returned slices borrow the stream's storage. They may be invalidated by a later write that reallocates the buffer.

Migrating from the original version

Zig 0.16 changed std.ArrayList to the unmanaged form. Replace direct struct construction:

// Old
var stream = binaryStream{
    .buff = std.ArrayList(u8).init(allocator),
    .offset = 0,
};

// Zig 0.16
var stream = BinaryStream.init(allocator);
defer stream.deinit();

The old type name binaryStream and method names writeStrL, writeStrL8, readStringL, readStringL8, read16, and readUInt64 remain available as compatibility aliases. New code should use BinaryStream and the current names.

read and string-reading methods now return []const u8, because the returned memory is borrowed from the stream.

Development

zig fmt --check build.zig binary.zig
zig build test
zig build test -Doptimize=ReleaseSafe

CI also compile-checks 32-bit x86 and AArch64 targets to catch assumptions about pointer width and integer encoding.

About

zig binarystream

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages