Zig modules for unsigned varints, multicodec, multibase, multihash, and CIDs.
Add to build.zig.zon
:
.{
// ...
.dependencies = .{
.multiformats = .{
.url = "https://github.com/nDimensional/zig-multiformats/archive/refs/tags/v0.1.0.tar.gz",
// .hash = "...",
},
}
}
Then in build.zig
:
pub fn build(b: *std.Build) !void {
// ...
const multiformats = b.dependency("multiformats", .{});
const varint = multiformats.module("varint");
const multicodec = multiformats.module("multicodec");
const multibase = multiformats.module("multibase");
const multihash = multiformats.module("multihash");
const cid = multiformats.module("cid");
// ... add as imports to exe or lib
}
pub const MAX_BYTE_LENGTH = 9;
pub const MAX_VALUE: u64 = 1 << 63;
pub fn encodingLength(val: u64) usize
pub fn decode(buf: []const u8, len: ?*usize) !usize
pub fn encode(buf: []u8, val: u64) usize
pub fn read(reader: std.io.AnyReader) !u64
pub fn write(writer: std.io.AnyWriter, val: u64) !void
The varint
module has read
/write
for usage with streams, and encode
/decode
for usage with slices. Trying to encode
to a buffer that is too small will panic; always check that it has sufficient size using encodingLength(val)
first.
The different bases are exported as type-erased Base
interface structs.
pub const Base = struct {
code: Code,
name: []const u8,
impl: type,
pub fn writeAll(self: Base, writer: std.io.AnyWriter, bytes: []const u8) !void
pub fn encode(self: Base, allocator: std.mem.Allocator, bytes: []const u8) ![]const u8
pub fn baseEncode(self: Base, allocator: std.mem.Allocator, bytes: []const u8) ![]const u8
pub fn decode(self: Base, allocator: std.mem.Allocator, str: []const u8) ![]const u8
pub fn baseDecode(self: Base, allocator: std.mem.Allocator, str: []const u8) ![]const u8
};
// Base-X family - these are limited to encoding 256 bytes or less
pub const base10: Base;
pub const base36: Base;
pub const base36upper: Base;
pub const base58btc: Base;
pub const base58flickr: Base;
// RFC 4648 family - these are suitable for streaming / arbitrarily long encodings
pub const base2: Base;
pub const base8: Base;
pub const base16: Base;
pub const base16upper: Base;
pub const base32: Base;
pub const base32upper: Base;
pub const base32pad: Base;
pub const base32padupper: Base;
pub const base32hex: Base;
pub const base32hexupper: Base;
pub const base32hexpad: Base;
pub const base32hexpadupper: Base;
pub const base32z: Base;
pub const base64: Base;
pub const base64pad: Base;
pub const base64url: Base;
pub const base64urlpad: Base;
Additionally, there are "generic" encode/decode methods that use the multibase.Code
enum.
pub const Code = enum {
base10,
base36,
base36upper,
base58btc,
base58flickr,
base2,
base8,
base16,
base16upper,
base32,
base32upper,
base32pad,
base32padupper,
base32hex,
base32hexupper,
base32hexpad,
base32hexpadupper,
base32z,
base64,
base64pad,
base64url,
base64urlpad,
};
pub const DecodeResult = struct {
code: Code,
data: []const u8,
};
pub fn decode(allocator: std.mem.Allocator, str: []const u8) !DecodeResult
pub fn encode(allocator: std.mem.Allocator, bytes: []const u8, code: Code) ![]const u8
multicodec.Codec
is an enum containing every entry in the multicodec table. The enum type is u32
and the enum value is the multicodec code. Many of the multicodec names have dashes and thus must be escaped in Zig code like this:
const multicodec = @import("multicodec");
const code = multicodec.Codec.@"sha2-256";
const std = @import("std");
const varint = @import("varint");
const multibase = @import("multibase");
const multicodec = @import("multicodec");
pub const Digest = struct {
code: multicodec.Codec,
hash: []const u8,
/// decode a binary multihash from bytes
pub fn decode(allocator: std.mem.Allocator, bytes: []const u8) !Digest;
/// read a binary multihash from a reader
pub fn read(allocator: std.mem.Allocator, reader: std.io.AnyReader) !Digest;
pub fn deinit(self: Digest, allocator: std.mem.Allocator) void;
pub fn copy(self: Digest, allocator: std.mem.Allocator) !Digest;
pub fn eql(self: Digest, other: Digest) bool;
pub fn expectEqual(actual: Digest, expected: Digest) !void;
pub fn encodingLength(self: Digest) usize;
pub fn encode(self: Digest, allocator: std.mem.Allocator) ![]const u8;
pub fn write(self: Digest, writer: std.io.AnyWriter) !void;
/// Format a human-readable {code}-{len}-{hex} string for a Digest
pub fn format(self: Digest, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void;
};
pub const CID = struct {
pub const Version = enum { cidv0, cidv1 };
version: Version,
codec: Codec,
digest: Digest,
/// parse a CID from multibase-encoded string
pub fn parse(allocator: std.mem.Allocator, str: []const u8) !CID;
/// read a binary CID from a reader
pub fn read(allocator: std.mem.Allocator, reader: std.io.AnyReader) !CID;
/// decode a binary CID from bytes
pub fn decode(allocator: std.mem.Allocator, bytes: []const u8) !CID;
pub fn deinit(self: CID, allocator: std.mem.Allocator) void;
pub fn copy(self: CID, allocator: std.mem.Allocator) !CID;
pub fn eql(self: CID, other: CID) bool;
pub fn expectEqual(actual: CID, expected: CID) !void;
pub fn encodingLength(self: CID) usize;
pub fn write(self: CID, writer: std.io.AnyWriter) !void;
pub fn encode(self: CID, allocator: std.mem.Allocator) ![]const u8;
/// Return a multibase Formatter for a CID
pub fn formatBase(self: CID, base: multibase.Code) std.fmt.Formatter(formatBaseImpl);
/// Return a human-readable string Formatter for a CID
pub fn formatString(self: CID) std.fmt.Formatter(formatStringImpl);
};