A minimal, idiomatic Zig wrapper around LevelDB's C API.
-
Zig fetch
zig fetch --save=leveldb git+https://github.com/chainsafe/leveldb.zig
-
In your
build.zig, link the dependencyconst leveldb_module = b.dependency("leveldb", .{}).module("leveldb"); my_module.addImport("leveldb", leveldb_module);
-
Import and use in your code:
const leveldb = @import("leveldb");
Here's a simple example to get you started:
const std = @import("std");
const leveldb = @import("leveldb");
pub fn main() !void {
// Create options
var options = leveldb.Options.create();
defer options.destroy();
options.setCreateIfMissing(true);
// Open database
var db = try leveldb.DB.open(&options, "/tmp/testdb");
defer db.close();
// Put a key-value pair
var write_opts = leveldb.WriteOptions.create();
defer write_opts.destroy();
try db.put(&write_opts, "hello", "world");
// Get the value
var read_opts = leveldb.ReadOptions.create();
defer read_opts.destroy();
const value = try db.get(&read_opts, "hello");
if (value) |v| {
std.debug.print("Value: {s}\n", .{v});
// IMPORTANT: Free the memory allocated by LevelDB
leveldb.free(v.ptr);
}
}DB: Main database handle for operations likeput,get,delete.Options: Configuration for database creation (compression, cache, etc.).Iterator: For traversing key-value pairs in order.WriteBatch: Groups multiple write operations atomically.Snapshot: Provides consistent read views.Cache: LRU cache for block caching.Comparator: Custom key comparison logic.FilterPolicy: Bloom filter for read optimization.
- Database Management:
DB.open(),DB.close(),destroyDB(),repairDB() - CRUD Operations:
DB.put(),DB.get(),DB.delete() - Iteration:
DB.createIterator(),Iterator.seek(),Iterator.next() - Batching:
WriteBatch.put(),DB.write() - Snapshots:
DB.createSnapshot(),ReadOptions.setSnapshot() - Utilities:
free()for memory management
All operations return Error!T where Error includes:
Corruption: Database corruptionInvalidArgument: Bad inputIOError: File system issuesUnknown: Other errors
// Open database
var options = leveldb.Options.create();
options.setCreateIfMissing(true);
var db = try leveldb.DB.open(&options, "/tmp/mydb");
// Put and get
try db.put(&leveldb.WriteOptions.create(), "key1", "value1");
const val = try db.get(&leveldb.ReadOptions.create(), "key1");
if (val) |v| {
// Use v...
// Then free v
leveldb.free(v);
}
// Delete
try db.delete(&leveldb.WriteOptions.create(), "key1");
// Close
db.close();
options.destroy();var iter = db.createIterator(&leveldb.ReadOptions.create());
defer iter.destroy();
iter.seekToFirst();
while (iter.valid()) {
const key = iter.key();
const value = iter.value();
// Process key/value (valid until next iterator move)
std.debug.print("{s} = {s}\n", .{key, value});
iter.next();
}var batch = leveldb.WriteBatch.create();
defer batch.destroy();
batch.put("key1", "val1");
batch.put("key2", "val2");
batch.delete("old_key");
try db.write(&leveldb.WriteOptions.create(), &batch);var snapshot = db.createSnapshot();
defer db.releaseSnapshot(&snapshot);
var read_opts = leveldb.ReadOptions.create();
read_opts.setSnapshot(&snapshot);
// Reads will see DB state at snapshot timeDB.get() and DB.propertyValue() return slices pointing to C-allocated memory. You must call leveldb.free(slice) after use to avoid memory leaks.
Iterator key() and value() return slices valid only until the next iterator operation or DB modification.
MIT