- Zig 100%
|
|
||
|---|---|---|
| src | flattened Page.Header into Page | |
| .gitignore | initial commit with project boilerplate | |
| build.zig | finalizing details for initial release | |
| build.zig.zon | version bump to v1.1.0 | |
| CHANGELOG.md | version bump to v1.1.0 | |
| LICENSE | initial commit with project boilerplate | |
| README.md | version bump to v1.1.0 | |
ogg
A zero-allocation, stream-oriented parser for structural Ogg containers. Fully implements the RFC-3533 specification.
Features
- Zero Allocation: Operates entirely on stream cursors and user-provided stack/heap buffers.
- PacketReader API: Streams logical packets, isolating their payloads into child
Packettypes, which are essentially bounded child-readers that implement astd.Io.Readerinterface, but isolated only to the payload of the packet. This API is suitable for encodings that rely upon packet-based structures, such as Vorbis and Opus. - Reader API: Streams the data of the container as one continuous stream of bytes, transparently handling all pages, lacing values, and packets, implemented as a
std.Io.Readerinterface. This API is suitable for encodings that perform their own framing, such as Ogg/FLAC. - Clean Domain Separation: Focuses exclusively on file structure layout; interpreting data schemas (like audio decoding or text metadata parsing) is completely deferred to your application logic.
- No AI/LLM Code: 100% of the code is both inspired and written by a human.
Installation
Add ogg to your build.zig.zon dependencies:
.dependencies=.{.ogg=.{.url="https://codeberg.org/audiophile/ogg/archive/v1.1.0.tar.gz",// .hash = "...",},},Expose the module in your build.zig:
constogg_dep=b.dependency("ogg",.{.target=target,.optimize=optimize,});exe.root_module.addImport("ogg",ogg_dep.module("ogg"));Quick Start
PacketReader API
The PacketReader is an iterative reader that yields logical packets in the stream.
A Packet is not actually read out of the stream ahead of time, nor require any allocation. It only logically creates the boundaries of the packet based on the Ogg pages encountered in the stream, which is completely transparent to the user.
conststd=@import("std");constogg=@import("ogg");pubfnmain(_:std.process.Init)!void{// Accepts any data source in a std.Io.Reader.vardata=@embedFile("filename.ogg");varreader:std.Io.Reader=.fixed(data);// Initialize the packet iteratorvarpacket_buffer:[4096]u8=undefined;varpacket_reader:ogg.PacketReader=.{.source=&reader,.buffer=&packet_buffer,};// Read packets in a loopwhile(trypacket_reader.next())|packet|{// Read packet as normal std.Io.Readerconstnumber=packet.reader.takeInt(u32,.big);constarray=packet.reader.takeArray(16);// The packet reader ensures that packets are fully consumed before// reading the next, but it hurts nothing to do so yourself._=trypacket.reader.discardRemaining();}}Reader API
The Reader provides a basic "dumb" std.Io.Reader that views the Ogg stream as a contiguous stream of bytes that are being provided in a container. Packets pass through it seamlessly as pure data, the caller need not concern themselves when one packet begins and another ends, or when a new page boundary is crossed.
conststd=@import("std");constogg=@import("ogg");pubfnmain(_:std.process.Init)!void{// Accepts any data source in a std.Io.Reader.vardata=@embedFile("filename.ogg");varreader:std.Io.Reader=.fixed(data);// Initialize the Ogg readervarbuffer:[4096]u8=undefined;varogg_reader=ogg.Reader.init(&reader,&buffer);// Example scratch buffer for reading intovarread_buffer:[16384]u8=undefined;while(true){// Use interface field to access std.Io.Reader implementation.constn=tryogg_reader.interface.readSliceShort(&read_buffer);if(n<read_buffer.len)break;// Process data as contiguous stream of bytes for whatever you need}}Seeking
The Ogg container itself does not implement any seek functionality, as this is dependent on the encoding of the data it contains, which implements its own logic.
That said, and regardless of which API you choose, each has a resync function implemented to synchronize the stream from an arbitrary offset in the reader. So whether you are picking up in the middle of a network stream or had to drop a corrupted packet, both APIs are capable of recovering and returning to a valid state.
License
This project is licensed under the MIT License.