Skip to content

Instantly share code, notes, and snippets.

@Lightnet
Created June 25, 2026 05:39
Show Gist options
  • Select an option

  • Save Lightnet/d893b2263478398e6b514d42f119c402 to your computer and use it in GitHub Desktop.

Select an option

Save Lightnet/d893b2263478398e6b514d42f119c402 to your computer and use it in GitHub Desktop.
sample database struct AI base model test.
// zig 0.16.0
const std = @import("std");
pub const User = struct {
id: u32,
name: []const u8,
date: []const u8,
};
pub fn Table(comptime T: type) type {
const type_info = @typeInfo(T);
if (type_info != .@"struct") {
@compileError("Table type must be a struct");
}
if (!@hasField(T, "id") or @TypeOf(@field(@as(T, undefined), "id")) != u32) {
@compileError("Table struct must contain an 'id: u32' field for indexing");
}
return struct {
rows: std.ArrayList(T),
index_map: std.array_hash_map.Auto(u32, usize),
allocator: std.mem.Allocator,
pub fn init(allocator: std.mem.Allocator) @This() {
return .{
.rows = .empty,
.index_map = .empty,
.allocator = allocator,
};
}
pub fn deinit(self: *@This()) void {
// Safely frees every string because the table now guarantees 100% ownership
for (self.rows.items) |row| {
inline for (@typeInfo(T).@"struct".fields) |field| {
if (field.type == []const u8 or field.type == []u8) {
self.allocator.free(@field(row, field.name));
}
}
}
self.rows.deinit(self.allocator);
self.index_map.deinit(self.allocator);
}
pub fn insert(self: *@This(), record: T) !void {
const new_idx = self.rows.items.len;
if (self.index_map.contains(record.id)) return error.DuplicatePrimaryKey;
// FIXED: Automatically duplicate string fields so the database owns its memory
var owned_record = record;
inline for (@typeInfo(T).@"struct".fields) |field| {
if (field.type == []const u8 or field.type == []u8) {
const original_str = @field(record, field.name);
@field(owned_record, field.name) = try self.allocator.dupe(u8, original_str);
}
}
try self.rows.append(self.allocator, owned_record);
try self.index_map.put(self.allocator, record.id, new_idx);
}
pub fn findById(self: *@This(), id: u32) ?*T {
const idx = self.index_map.get(id) orelse return null;
return &self.rows.items[idx];
}
fn readExact(reader: anytype, dest: []u8) !void {
for (dest) |*b| {
b.* = try reader.takeByte();
}
}
pub fn saveToFile(self: *@This(), io: std.Io, path: []const u8) !void {
var file = try std.Io.Dir.createFileAbsolute(io, path, .{});
defer file.close(io);
var buf: [4096]u8 = undefined;
var file_writer = file.writer(io, &buf);
const writer = &file_writer.interface;
var len_buf: [8]u8 = undefined;
std.mem.writeInt(u64, &len_buf, self.rows.items.len, .little);
try writer.writeAll(&len_buf);
for (self.rows.items) |row| {
var id_buf: [4]u8 = undefined;
std.mem.writeInt(u32, &id_buf, row.id, .little);
try writer.writeAll(&id_buf);
var name_len_buf: [4]u8 = undefined;
std.mem.writeInt(u32, &name_len_buf, @as(u32, @intCast(row.name.len)), .little);
try writer.writeAll(&name_len_buf);
try writer.writeAll(row.name);
var date_len_buf: [4]u8 = undefined;
std.mem.writeInt(u32, &date_len_buf, @as(u32, @intCast(row.date.len)), .little);
try writer.writeAll(&date_len_buf);
try writer.writeAll(row.date);
}
try file_writer.flush();
}
pub fn loadFromFile(self: *@This(), io: std.Io, path: []const u8) !void {
var file = try std.Io.Dir.openFileAbsolute(io, path, .{ .mode = .read_only });
defer file.close(io);
var buf: [4096]u8 = undefined;
var file_reader = file.reader(io, &buf);
const reader = &file_reader.interface;
var len_buf: [8]u8 = undefined;
try readExact(reader, &len_buf);
const total_rows = std.mem.readInt(u64, &len_buf, .little);
var i: usize = 0;
while (i < total_rows) : (i += 1) {
var id_buf: [4]u8 = undefined;
try readExact(reader, &id_buf);
const id = std.mem.readInt(u32, &id_buf, .little);
// Read into a temporary buffer, let insert copy it, then free it
var name_len_buf: [4]u8 = undefined;
try readExact(reader, &name_len_buf);
const name_len = std.mem.readInt(u32, &name_len_buf, .little);
const temp_name = try self.allocator.alloc(u8, name_len);
defer self.allocator.free(temp_name);
try readExact(reader, temp_name);
var date_len_buf: [4]u8 = undefined;
try readExact(reader, &date_len_buf);
const date_len = std.mem.readInt(u32, &date_len_buf, .little);
const temp_date = try self.allocator.alloc(u8, date_len);
defer self.allocator.free(temp_date);
try readExact(reader, temp_date);
// insert will cleanly duplicate them into persistent database memory
try self.insert(.{
.id = id,
.name = temp_name,
.date = temp_date,
});
}
}
};
}
pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var threaded: std.Io.Threaded = .init_single_threaded;
const io = threaded.io();
var stdout_file = std.Io.File.stdout();
var file_writer = stdout_file.writer(io, &.{});
const stdout = &file_writer.interface;
// 1. DYNAMIC PATHING: Fetch the running application workspace directory [1.1]
const cwd_path = try std.process.currentPathAlloc(io, allocator);
defer allocator.free(cwd_path);
// 2. Build absolute destination path
const filename = "users.dat";
const absolute_db_path = try std.fs.path.join(allocator, &.{ cwd_path, filename });
defer allocator.free(absolute_db_path);
// 3. EXISTENCE CHECK: Verify if file exists [1.1]
var file_exists = true;
std.Io.Dir.accessAbsolute(io, absolute_db_path, .{}) catch |err| {
if (err == error.FileNotFound) file_exists = false else return err;
};
var db = Table(User).init(allocator);
defer db.deinit();
if (file_exists) {
try db.loadFromFile(io, absolute_db_path);
try stdout.print("Database loaded complete!\n\n", .{});
// if (db.findById(101)) |user| {
// try stdout.print("-> Restored Primary Key ID 20: Name={s}, Date={s}\n", .{ user.name, user.date });
// }
for (db.rows.items) |*row| {
try stdout.print("ID: {}, Name: {s}\n", .{ row.id, row.name });
}
} else {
try db.insert(.{ .id = 101, .name = "Alice", .date = "2026-01-15" });
try db.insert(.{ .id = 20, .name = "Bob", .date = "2026-06-24" });
try db.saveToFile(io, absolute_db_path);
try stdout.print("Database save complete!\n\n", .{});
}
}
// pub fn main() !void {
// var gpa = std.heap.DebugAllocator(.{}){};
// defer _ = gpa.deinit();
// const allocator = gpa.allocator();
// var threaded: std.Io.Threaded = .init_single_threaded;
// const io = threaded.io();
// var stdout_file = std.Io.File.stdout();
// var file_writer = stdout_file.writer(io, &.{});
// const stdout = &file_writer.interface;
// const db_path = "x:\\xxx\\users.dat";
// // const db_path = "users.dat";
// // {
// // try stdout.print("=== Phase 1: populating and saving database ===\n", .{});
// // var write_db = Table(User).init(allocator);
// // defer write_db.deinit();
// // try write_db.insert(.{ .id = 10, .name = "Alice", .date = "2026-01-15" });
// // try write_db.insert(.{ .id = 20, .name = "Bob", .date = "2026-06-24" });
// // try stdout.print("Saving database file to disk...\n", .{});
// // try write_db.saveToFile(io, db_path);
// // try stdout.print("Database file serialized successfully!\n\n", .{});
// // }
// {
// try stdout.print("=== Phase 2: instantiating empty engine & reading from file ===\n", .{});
// var read_db = Table(User).init(allocator);
// defer read_db.deinit();
// try stdout.print("Loading data records into memory...\n", .{});
// try read_db.loadFromFile(io, db_path);
// try stdout.print("Database restoration complete!\n\n", .{});
// try stdout.print("Verifying fast index lookups from loaded records:\n", .{});
// if (read_db.findById(20)) |user| {
// try stdout.print("-> Restored Primary Key ID 20: Name={s}, Date={s}\n", .{ user.name, user.date });
// }
// if (read_db.findById(10)) |user| {
// try stdout.print("-> Restored Primary Key ID 10: Name={s}, Date={s}\n", .{ user.name, user.date });
// }
// }
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment