Application Context Implementation #4

Closed
kayomn wants to merge 93 commits from event-loop-dev into main
2 changed files with 1 additions and 262 deletions
Showing only changes of commit 5a913ef0f8 - Show all commits

10
.vscode/launch.json vendored
View File

@ -10,15 +10,7 @@
"valuesFormatting": "parseText", "valuesFormatting": "parseText",
"preLaunchTask": "Build Debug", "preLaunchTask": "Build Debug",
}, },
{
"name": "Oar",
"type": "gdb",
"request": "launch",
"target": "${workspaceFolder}/zig-out/bin/oar",
"cwd": "${workspaceRoot}",
"valuesFormatting": "parseText",
"preLaunchTask": "Build Debug",
},
{ {
"name": "Test", "name": "Test",
"type": "gdb", "type": "gdb",

View File

@ -1,253 +0,0 @@
const core = @import("core");
const std = @import("std");
///
///
///
pub const Archive = struct {
pub fn deinit(archive: *Archive) {
}
pub fn init(file_system: *const sys.FileSystem, file_path: sys.Path) {
}
};
///
/// An entry block of an Oar archive file.
///
/// Typically, following the block in memory is the file data it holds the meta-information for.
///
pub const Entry = extern struct {
signature: [signature_magic.len]u8 = signature_magic,
revision: u8,
path: Path,
file_size: u64,
absolute_offset: u64,
padding: [232]u8 = std.mem.zeroes([232]u8),
comptime {
const entry_size = @sizeOf(Entry);
if (entry_size != 512)
@compileError("Entry is " ++
std.fmt.comptimePrint("{d}", .{entry_size}) ++ " bytes");
}
///
/// Attempts to read the next [Entry] from `file_access`.
///
/// Returns the read [Entry], `null` if there is no more to read, or a
/// [core.io.FileAccess.Error] if it failed.
///
pub fn next(file_access: core.io.FileAccess) core.io.FileAccess.Error!?Entry {
const mem = std.mem;
var entry = mem.zeroes(Entry);
const origin = try file_access.queryCursor();
if (((try file_access.read(mem.asBytes(&entry))) != @sizeOf(Entry)) and
core.io.equals(u8, &entry.signature, &signature_magic)) {
try file_access.seek(origin);
return null;
}
return entry;
}
///
/// Magic identifier used to validate [Entry] data.
///
pub const signature_magic = [3]u8{'o', 'a', 'r'};
};
///
/// Unique identifier pointing to an entry within an archive.
///
/// A path does not do any verification that the given entry pointed to actually exists.
///
pub const Path = extern struct {
buffer: [255]u8,
length: u8,
///
/// [Error.TooLong] occurs when creating a path that is greater than the maximum path size **in
/// bytes**.
///
pub const Error = error {
TooLong,
};
///
/// An empty [Path] with a length of `0`.
///
pub const empty = std.mem.zeroes(Path);
///
/// Returns `true` if `this_path` is equal to `that_path, otherwise `false`.
///
pub fn equals(this_path: Path, that_path: Path) bool {
return core.io.equals(u8, this_path.buffer[0 ..this_path.
length], that_path.buffer[0 .. that_path.length]);
}
///
/// Returns the hash of the text in `path`.
///
pub fn hash(path: Path) usize {
return core.io.hashBytes(path.buffer[0 .. path.length]);
}
///
/// Attempts to create a [Path] with the path components in `sequences` as a fully qualified
/// path from root.
///
/// A [Path] value is returned containing the fully qualified path from the file-system root or
/// a [Error] if it could not be created.
///
pub fn joined(sequences: []const []const u8) Error!Path {
var path = empty;
if (sequences.len != 0) {
const last_sequence_index = sequences.len - 1;
for (sequences) |sequence, index| if (sequence.len != 0) {
var components = core.io.Spliterator(u8){
.source = sequence,
.delimiter = "/",
};
while (components.next()) |component| if (component.len != 0) {
for (component) |byte| {
if (path.length == max) return error.TooLong;
path.buffer[path.length] = byte;
path.length += 1;
}
if (components.hasNext()) {
if (path.length == max) return error.TooLong;
path.buffer[path.length] = '/';
path.length += 1;
}
};
if (index < last_sequence_index) {
if (path.length == max) return error.TooLong;
path.buffer[path.length] = '/';
path.length += 1;
}
};
}
return path;
}
///
/// Maximum number of **bytes** in a [Path].
///
pub const max = 255;
///
/// Textual separator between components of a [Path].
///
pub const seperator = '/';
};
test "Path" {
const testing = std.testing;
const empty_path = Path.empty;
try testing.expectEqual(empty_path.length, 0);
try testing.expect(empty_path.equals(Path.empty));
const joined_component_path = try Path.joined(&.{"path", "to/my", "/file"});
const joined_normalized_path = try Path.joined(&.{"path/to/my/file"});
try testing.expectEqual(joined_component_path.length, joined_normalized_path.length);
try testing.expect(joined_component_path.equals(joined_normalized_path));
}
///
/// Starts the **O**na **Ar**chive packer utility.
///
pub fn main() u8 {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(!gpa.deinit());
const allocator = gpa.allocator();
const out_writer = std.io.getStdOut().writer();
const process = std.process;
const args = process.argsAlloc(allocator) catch {
out_writer.print("Failed to allocate args memory\n", .{}) catch undefined;
return 1;
};
defer process.argsFree(allocator, args);
if (args.len < 2) {
out_writer.print("Usage: oar [OPTION]... [FILE]...\n", .{}) catch undefined;
out_writer.print("Options and arguments\n", .{}) catch undefined;
return 0;
}
const arg = std.mem.sliceTo(args[1], 0);
if (core.io.equals(u8, arg, "--create")) {
if (args.len < 3) {
out_writer.print("Expected output file specified after `--create`\n", .{}) catch undefined;
return 1;
}
var archive = Archive.init(allocator, Path.joined(&.{args[2]})) catch {
out_writer.print("Failed to initialize archive for create\n", .{}) catch undefined;
return 1;
};
defer archive.deinit();
for (args[3 .. ]) |input_file_path| {
const file = std.fs.cwd().openFile(input_file_path) catch {
out_writer.print("Failed to open {s}\n", .{input_file_path}) catch undefined;
return 1;
};
defer file.close();
var entry = archive.open(Path.joined(&.{input_file_path})) catch {
out_writer.print("Failed to open {s}\n", .{input_file_path}) catch undefined;
return 1;
};
defer archive.close(entry);
var copy_buffer = std.mem.zeroes([4096]u8);
while (true) {
const read = try file.read(&copy_buffer);
if (read == 0) break;
try entry.write(copy_buffer[read ..]);
}
}
return 0;
}
out_writer.print("Unrecognized command-line option `{s}`\n", .{arg}) catch undefined;
return 0;
}