const std = @import("std"); const os = std.os; const fs = std.fs; const Allocator = std.mem.Allocator; const Corpus = @import("Corpus.zig"); const DB = @import("DB.zig"); const ErrCtx = @import("ErrCtx.zig"); const InvalidHeader = @import("header.zig").Invalid; const File = @This(); db: DB, ptr: []align(4096) const u8, pub const Error = os.OpenError || os.FStatError || os.MMapError || InvalidHeader; pub fn open(fname: []const u8) Error!File { const fd = try os.open(fname, os.O.RDONLY, 0); var fd_open = true; errdefer if (fd_open) os.close(fd); const st = try os.fstat(fd); const size = @intCast(usize, st.size); const ptr = try os.mmap(null, size, os.PROT.READ, os.MAP.SHARED, fd, 0); errdefer os.munmap(ptr); os.close(fd); fd_open = false; const db = try DB.fromBytes(ptr); return File{ .db = db, .ptr = ptr }; } pub fn close(self: *File) void { os.munmap(self.ptr); self.* = undefined; } const testing = std.testing; pub const TestDB = struct { file: File, dir: testing.TmpDir, path: [:0]const u8, allocator: Allocator, pub fn init(allocator: Allocator) !TestDB { var errc = ErrCtx{}; var corpus = try Corpus.testCorpus(allocator); defer corpus.deinit(); var db = try DB.fromCorpus(allocator, &corpus, &errc); defer db.deinit(allocator); var tmp = testing.tmpDir(.{}); errdefer tmp.cleanup(); const base_path = blk: { const relative_path = try fs.path.join(allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..], }); const real_path = try fs.realpathAlloc(allocator, relative_path); allocator.free(relative_path); break :blk real_path; }; const full_path = try fs.path.joinZ(allocator, &[_][]const u8{ base_path, "db.turbo", }); allocator.free(base_path); const mode = os.O.RDWR | os.O.CREAT | os.O.EXCL; const fd = try os.openat(tmp.dir.fd, "db.turbo", mode, 0o666); defer os.close(fd); _ = try os.writev(fd, db.iov().constSlice()); return TestDB{ .file = try open(full_path), .dir = tmp, .path = full_path, .allocator = allocator, }; } pub fn deinit(self: *TestDB) void { self.dir.cleanup(); self.allocator.free(self.path); } };