Application Context Implementation #4
42
build.zig
42
build.zig
|
@ -1,21 +1,28 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Builds the engine, tools, and dependencies of all.
|
||||||
|
///
|
||||||
pub fn build(builder: *std.build.Builder) void {
|
pub fn build(builder: *std.build.Builder) void {
|
||||||
const target = builder.standardTargetOptions(.{});
|
const target = builder.standardTargetOptions(.{});
|
||||||
const mode = builder.standardReleaseOptions();
|
const mode = builder.standardReleaseOptions();
|
||||||
|
const ona_pkg = projectPkg("ona", &.{});
|
||||||
|
|
||||||
// Ona executable.
|
// Engine executable.
|
||||||
{
|
{
|
||||||
const ona_exe = builder.addExecutable("ona", "./src/main.zig");
|
const engine_exe = builder.addExecutable("ona", "./src/engine/main.zig");
|
||||||
|
const oar_pkg = projectPkg("oar", &.{ona_pkg});
|
||||||
|
|
||||||
ona_exe.setTarget(target);
|
engine_exe.addPackage(oar_pkg);
|
||||||
ona_exe.setBuildMode(mode);
|
engine_exe.addPackage(ona_pkg);
|
||||||
ona_exe.install();
|
engine_exe.setTarget(target);
|
||||||
ona_exe.addIncludeDir("./ext");
|
engine_exe.setBuildMode(mode);
|
||||||
ona_exe.linkSystemLibrary("SDL2");
|
engine_exe.install();
|
||||||
ona_exe.linkLibC();
|
engine_exe.addIncludeDir("./ext");
|
||||||
|
engine_exe.linkSystemLibrary("SDL2");
|
||||||
|
engine_exe.linkLibC();
|
||||||
|
|
||||||
const run_cmd = ona_exe.run();
|
const run_cmd = engine_exe.run();
|
||||||
|
|
||||||
run_cmd.step.dependOn(builder.getInstallStep());
|
run_cmd.step.dependOn(builder.getInstallStep());
|
||||||
|
|
||||||
|
@ -24,6 +31,11 @@ pub fn build(builder: *std.build.Builder) void {
|
||||||
builder.step("run", "Run Ona application").dependOn(&run_cmd.step);
|
builder.step("run", "Run Ona application").dependOn(&run_cmd.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Oar executable.
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Ona tests.
|
// Ona tests.
|
||||||
{
|
{
|
||||||
const ona_tests = builder.addTestExe("test", "./src/main.zig");
|
const ona_tests = builder.addTestExe("test", "./src/main.zig");
|
||||||
|
@ -33,3 +45,15 @@ pub fn build(builder: *std.build.Builder) void {
|
||||||
builder.step("test", "Run Ona unit tests").dependOn(&ona_tests.step);
|
builder.step("test", "Run Ona unit tests").dependOn(&ona_tests.step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns a [std.build.Pkg] within the project codebase path at `name` with `dependencies` as its
|
||||||
|
/// dependencies.
|
||||||
|
///
|
||||||
|
fn projectPkg(comptime name: []const u8, dependencies: []const std.build.Pkg) std.build.Pkg {
|
||||||
|
return std.build.Pkg{
|
||||||
|
.name = name,
|
||||||
|
.path = .{.path = "./src/" ++ name ++ "/main.zig"},
|
||||||
|
.dependencies = dependencies,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
const ext = @cImport({
|
const ona = @import("ona");
|
||||||
@cInclude("SDL2/SDL.h");
|
|
||||||
});
|
|
||||||
|
|
||||||
const io = @import("./io.zig");
|
|
||||||
const stack = @import("./stack.zig");
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const sys = @import("./sys.zig");
|
const sys = @import("./sys.zig");
|
||||||
|
|
||||||
|
@ -14,13 +9,6 @@ pub fn main() anyerror!void {
|
||||||
return nosuspend await async sys.runGraphics(anyerror, run);
|
return nosuspend await async sys.runGraphics(anyerror, run);
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
|
||||||
_ = io;
|
|
||||||
_ = stack;
|
|
||||||
_ = std;
|
|
||||||
_ = sys;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run(app: *sys.AppContext, graphics: *sys.GraphicsContext) anyerror!void {
|
fn run(app: *sys.AppContext, graphics: *sys.GraphicsContext) anyerror!void {
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
|
||||||
|
@ -37,8 +25,7 @@ fn run(app: *sys.AppContext, graphics: *sys.GraphicsContext) anyerror!void {
|
||||||
|
|
||||||
defer allocator.free(buffer);
|
defer allocator.free(buffer);
|
||||||
|
|
||||||
if ((try file_access.read(buffer)) != file_size)
|
if ((try file_access.read(buffer)) != file_size) return error.ScriptLoadFailure;
|
||||||
return error.ScriptLoadFailure;
|
|
||||||
|
|
||||||
sys.Log.debug.write(buffer);
|
sys.Log.debug.write(buffer);
|
||||||
}
|
}
|
||||||
|
@ -47,3 +34,7 @@ fn run(app: *sys.AppContext, graphics: *sys.GraphicsContext) anyerror!void {
|
||||||
graphics.present();
|
graphics.present();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
_ = sys;
|
||||||
|
}
|
|
@ -2,11 +2,8 @@ const ext = @cImport({
|
||||||
@cInclude("SDL2/SDL.h");
|
@cInclude("SDL2/SDL.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
const io = @import("./io.zig");
|
const oar = @import("oar");
|
||||||
const mem = @import("./mem.zig");
|
const ona = @import("ona");
|
||||||
const meta = @import("./meta.zig");
|
|
||||||
const oar = @import("./oar.zig");
|
|
||||||
const stack = @import("./stack.zig");
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -131,12 +128,14 @@ pub const AppContext = opaque {
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Initializes a new [Implemenation] with `data_access` as the data archive to read from
|
/// Initializes a new [Implemenation] with `data_archive_file_access` as the data archive to
|
||||||
/// and `user_path_prefix` as the native writable user data directory.
|
/// read from and `user_path_prefix` as the native writable user data directory.
|
||||||
///
|
///
|
||||||
/// Returns the created [Implementation] value on success or [InitError] on failure.
|
/// Returns the created [Implementation] value on success or [InitError] on failure.
|
||||||
///
|
///
|
||||||
fn init(allocator: std.mem.Allocator, data_access: FileAccess) InitError!Implementation {
|
fn init(allocator: std.mem.Allocator,
|
||||||
|
data_archive_file_access: ona.io.FileAccess) InitError!Implementation {
|
||||||
|
|
||||||
const user_path_prefix = ext.SDL_GetPrefPath("ona", "ona") orelse
|
const user_path_prefix = ext.SDL_GetPrefPath("ona", "ona") orelse
|
||||||
return error.OutOfMemory;
|
return error.OutOfMemory;
|
||||||
|
|
||||||
|
@ -149,7 +148,7 @@ pub const AppContext = opaque {
|
||||||
.user_path_prefix = user_path_prefix,
|
.user_path_prefix = user_path_prefix,
|
||||||
|
|
||||||
.data_file_system = .{.archive = .{
|
.data_file_system = .{.archive = .{
|
||||||
.instance = try oar.Archive.init(allocator, data_access),
|
.instance = try oar.Archive.init(allocator, data_archive_file_access),
|
||||||
}},
|
}},
|
||||||
|
|
||||||
.message_thread = null,
|
.message_thread = null,
|
||||||
|
@ -223,12 +222,12 @@ pub const AppContext = opaque {
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
pub fn schedule(app_context: *AppContext, procedure: anytype,
|
pub fn schedule(app_context: *AppContext, procedure: anytype,
|
||||||
arguments: anytype) meta.FnReturn(@TypeOf(procedure)) {
|
arguments: anytype) ona.meta.FnReturn(@TypeOf(procedure)) {
|
||||||
|
|
||||||
const Task = struct {
|
const Task = struct {
|
||||||
procedure: @TypeOf(procedure),
|
procedure: @TypeOf(procedure),
|
||||||
arguments: *@TypeOf(arguments),
|
arguments: *@TypeOf(arguments),
|
||||||
result: meta.FnReturn(@TypeOf(procedure)),
|
result: ona.meta.FnReturn(@TypeOf(procedure)),
|
||||||
|
|
||||||
const Task = @This();
|
const Task = @This();
|
||||||
|
|
||||||
|
@ -263,102 +262,6 @@ pub const AppContext = opaque {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
|
||||||
/// File-system agnostic abstraction for manipulating a file.
|
|
||||||
///
|
|
||||||
pub const FileAccess = struct {
|
|
||||||
context: *anyopaque,
|
|
||||||
implementation: *const Implementation,
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Provides a set of implementation-specific behaviors to a [FileAccess] instance.
|
|
||||||
///
|
|
||||||
pub const Implementation = struct {
|
|
||||||
close: fn (*anyopaque) void,
|
|
||||||
queryCursor: fn (*anyopaque) Error!u64,
|
|
||||||
queryLength: fn (*anyopaque) Error!u64,
|
|
||||||
read: fn (*anyopaque, []u8) Error!usize,
|
|
||||||
seek: fn (*anyopaque, u64) Error!void,
|
|
||||||
seekToEnd: fn (*anyopaque) Error!void,
|
|
||||||
skip: fn (*anyopaque, i64) Error!void,
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// [Error.FileInaccessible] is a generic catch-all for a [FileAccess] reference no longer
|
|
||||||
/// pointing to a file or the file becomming invalid for whatever reason.
|
|
||||||
///
|
|
||||||
pub const Error = error {
|
|
||||||
FileInaccessible,
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Close the file referenced by `file_access` on the main thread, invalidating the reference to
|
|
||||||
/// it and releasing any associated resources.
|
|
||||||
///
|
|
||||||
/// Freeing an invalid `file_access` has no effect on the file and logs a warning over the
|
|
||||||
/// wasted effort.
|
|
||||||
///
|
|
||||||
pub fn close(file_access: *FileAccess) void {
|
|
||||||
return file_access.implementation.close(file_access.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Attempts to query the current cursor position for the file referenced by `file_access`.
|
|
||||||
///
|
|
||||||
/// Returns the number of bytes into the file that the cursor is relative to its beginning or a
|
|
||||||
/// [Error] on failure.
|
|
||||||
///
|
|
||||||
pub fn queryCursor(file_access: *FileAccess) Error!u64 {
|
|
||||||
return file_access.implementation.queryCursor(file_access.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Attempts to query the current length for the file referenced by `file_access`.
|
|
||||||
///
|
|
||||||
/// Returns the current length of the file at the time of the operation or a [Error] if the file
|
|
||||||
/// failed to be queried.
|
|
||||||
///
|
|
||||||
pub fn queryLength(file_access: *FileAccess) Error!u64 {
|
|
||||||
return file_access.implementation.queryLength(file_access.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Attempts to read `file_access` from the its current position into `buffer`.
|
|
||||||
///
|
|
||||||
/// Returns the number of bytes that were available to be read, otherwise an [Error] on failure.
|
|
||||||
///
|
|
||||||
pub fn read(file_access: *FileAccess, buffer: []u8) Error!usize {
|
|
||||||
return file_access.implementation.read(file_access.context, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Attempts to seek `file_access` from the beginning of the file to `cursor` bytes.
|
|
||||||
///
|
|
||||||
/// Returns [Error] on failure.
|
|
||||||
///
|
|
||||||
pub fn seek(file_access: *FileAccess, cursor: u64) Error!void {
|
|
||||||
return file_access.implementation.seek(file_access.context, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Attempts to seek `file_access` to the end of the file.
|
|
||||||
///
|
|
||||||
/// Returns [Error] on failure.
|
|
||||||
///
|
|
||||||
pub fn seekToEnd(file_access: *FileAccess) Error!void {
|
|
||||||
return file_access.implementation.seekToEnd(file_access.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Attempts to seek `file_access` by `offset` from the current file position.
|
|
||||||
///
|
|
||||||
/// Returns [Error] on failure;
|
|
||||||
///
|
|
||||||
pub fn skip(file_access: *FileAccess, offset: i64) Error!void {
|
|
||||||
return file_access.implementation.skip(file_access.context, offset);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Platform-agnostic mechanism for working with an abstraction of the underlying file-system(s)
|
/// Platform-agnostic mechanism for working with an abstraction of the underlying file-system(s)
|
||||||
/// available to the application in a sandboxed environment.
|
/// available to the application in a sandboxed environment.
|
||||||
|
@ -447,11 +350,13 @@ pub const FileSystem = union(enum) {
|
||||||
/// Returns a [FileAccess] reference that provides access to the file referenced by `path`
|
/// Returns a [FileAccess] reference that provides access to the file referenced by `path`
|
||||||
/// or a [OpenError] if it failed.
|
/// or a [OpenError] if it failed.
|
||||||
///
|
///
|
||||||
pub fn open(path: Path, mode: OpenMode) OpenError!FileAccess {
|
pub fn open(path: Path, mode: OpenMode) OpenError!ona.io.FileAccess {
|
||||||
switch (path.file_system.*) {
|
switch (path.file_system.*) {
|
||||||
.archive => |*archive| {
|
.archive => |*archive| {
|
||||||
if (mode != .readonly) return error.ModeUnsupported;
|
if (mode != .readonly) return error.ModeUnsupported;
|
||||||
|
|
||||||
|
const FileAccess = ona.io.FileAccess;
|
||||||
|
|
||||||
for (archive.entry_table) |*entry| if (entry.owner == null) {
|
for (archive.entry_table) |*entry| if (entry.owner == null) {
|
||||||
const Implementation = struct {
|
const Implementation = struct {
|
||||||
fn close(context: *anyopaque) void {
|
fn close(context: *anyopaque) void {
|
||||||
|
@ -567,6 +472,8 @@ pub const FileSystem = union(enum) {
|
||||||
|
|
||||||
ext.SDL_ClearError();
|
ext.SDL_ClearError();
|
||||||
|
|
||||||
|
const FileAccess = ona.io.FileAccess;
|
||||||
|
|
||||||
const Implementation = struct {
|
const Implementation = struct {
|
||||||
fn rwOpsCast(context: *anyopaque) *ext.SDL_RWops {
|
fn rwOpsCast(context: *anyopaque) *ext.SDL_RWops {
|
||||||
return @ptrCast(*ext.SDL_RWops, @alignCast(
|
return @ptrCast(*ext.SDL_RWops, @alignCast(
|
||||||
|
@ -693,7 +600,7 @@ pub const FileSystem = union(enum) {
|
||||||
const last_sequence_index = sequences.len - 1;
|
const last_sequence_index = sequences.len - 1;
|
||||||
|
|
||||||
for (sequences) |sequence, index| if (sequence.len != 0) {
|
for (sequences) |sequence, index| if (sequence.len != 0) {
|
||||||
var components = mem.Spliterator(u8){
|
var components = ona.mem.Spliterator(u8){
|
||||||
.source = sequence,
|
.source = sequence,
|
||||||
.delimiter = "/",
|
.delimiter = "/",
|
||||||
};
|
};
|
|
@ -1,18 +1,17 @@
|
||||||
|
const ona = @import("ona");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const sys = @import("./sys.zig");
|
|
||||||
const table = @import("./table.zig");
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Thin file-wrapper and in-memory layout cache of an OAR archive file.
|
/// Thin file-wrapper and in-memory layout cache of an OAR archive file.
|
||||||
///
|
///
|
||||||
pub const Archive = struct {
|
pub const Archive = struct {
|
||||||
file_access: sys.FileAccess,
|
file_access: ona.io.FileAccess,
|
||||||
index_cache: IndexCache,
|
index_cache: IndexCache,
|
||||||
|
|
||||||
///
|
///
|
||||||
/// [OpenError.EntryNotFound] happens when an entry could not be found.
|
/// [OpenError.EntryNotFound] happens when an entry could not be found.
|
||||||
///
|
///
|
||||||
pub const FindError = sys.FileAccess.Error || error {
|
pub const FindError = ona.io.FileAccess.Error || error {
|
||||||
EntryNotFound,
|
EntryNotFound,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ pub const Archive = struct {
|
||||||
/// As the archive is queried via [find], the cache is lazily assembled with the absolute
|
/// As the archive is queried via [find], the cache is lazily assembled with the absolute
|
||||||
/// offsets of each queried file.
|
/// offsets of each queried file.
|
||||||
///
|
///
|
||||||
const IndexCache = table.Hashed([]const u8, u64, table.string_context);
|
const IndexCache = ona.table.Hashed([]const u8, u64, ona.table.string_context);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Deinitializes the index cache of `archive`, freeing all associated memory.
|
/// Deinitializes the index cache of `archive`, freeing all associated memory.
|
||||||
|
@ -49,6 +48,7 @@ pub const Archive = struct {
|
||||||
.header = find_header: {
|
.header = find_header: {
|
||||||
var header = Entry.Header{
|
var header = Entry.Header{
|
||||||
.revision = 0,
|
.revision = 0,
|
||||||
|
.path = Path.empty,
|
||||||
.file_size = 0,
|
.file_size = 0,
|
||||||
.absolute_offset = 0
|
.absolute_offset = 0
|
||||||
};
|
};
|
||||||
|
@ -73,7 +73,7 @@ pub const Archive = struct {
|
||||||
|
|
||||||
// Read first entry.
|
// Read first entry.
|
||||||
while ((try archive.file_access.read(mem.asBytes(&header))) == header_size) {
|
while ((try archive.file_access.read(mem.asBytes(&header))) == header_size) {
|
||||||
if (mem.eql(u8, entry_path, header.name_buffer[0 .. header.name_length])) {
|
if (mem.eql(u8, entry_path, header.path.buffer[0 .. header.path.length])) {
|
||||||
// If caching fails... oh well...
|
// If caching fails... oh well...
|
||||||
archive.index_cache.insert(entry_path, header.absolute_offset) catch {};
|
archive.index_cache.insert(entry_path, header.absolute_offset) catch {};
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ pub const Archive = struct {
|
||||||
/// **Note** that `archive_file_access` does nothing to manage the lifetime of the open file.
|
/// **Note** that `archive_file_access` does nothing to manage the lifetime of the open file.
|
||||||
///
|
///
|
||||||
pub fn init(cache_allocator: std.mem.Allocator,
|
pub fn init(cache_allocator: std.mem.Allocator,
|
||||||
archive_file_access: sys.FileAccess) InitError!Archive {
|
archive_file_access: ona.io.FileAccess) InitError!Archive {
|
||||||
|
|
||||||
return Archive{
|
return Archive{
|
||||||
.index_cache = try IndexCache.init(cache_allocator),
|
.index_cache = try IndexCache.init(cache_allocator),
|
||||||
|
@ -123,7 +123,7 @@ pub const Archive = struct {
|
||||||
/// Handles the state of an opened archive entry.
|
/// Handles the state of an opened archive entry.
|
||||||
///
|
///
|
||||||
pub const Entry = struct {
|
pub const Entry = struct {
|
||||||
owner: ?*sys.FileAccess,
|
owner: ?*ona.io.FileAccess,
|
||||||
cursor: u64,
|
cursor: u64,
|
||||||
header: Header,
|
header: Header,
|
||||||
|
|
||||||
|
@ -135,8 +135,7 @@ pub const Entry = struct {
|
||||||
pub const Header = extern struct {
|
pub const Header = extern struct {
|
||||||
signature: [signature_magic.len]u8 = signature_magic,
|
signature: [signature_magic.len]u8 = signature_magic,
|
||||||
revision: u8,
|
revision: u8,
|
||||||
name_buffer: [255]u8 = std.mem.zeroes([255]u8),
|
path: Path,
|
||||||
name_length: u8 = 0,
|
|
||||||
file_size: u64,
|
file_size: u64,
|
||||||
absolute_offset: u64,
|
absolute_offset: u64,
|
||||||
padding: [232]u8 = std.mem.zeroes([232]u8),
|
padding: [232]u8 = std.mem.zeroes([232]u8),
|
||||||
|
@ -155,3 +154,16 @@ pub const Entry = struct {
|
||||||
pub const signature_magic = [3]u8{'o', 'a', 'r'};
|
pub const signature_magic = [3]u8{'o', 'a', 'r'};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub const Path = extern struct {
|
||||||
|
buffer: [255]u8,
|
||||||
|
length: u8,
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub const empty = std.mem.zeroes(Path);
|
||||||
|
};
|
|
@ -1,6 +1,102 @@
|
||||||
const stack = @import("./stack.zig");
|
const stack = @import("./stack.zig");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
///
|
||||||
|
/// File-system agnostic abstraction for manipulating a file.
|
||||||
|
///
|
||||||
|
pub const FileAccess = struct {
|
||||||
|
context: *anyopaque,
|
||||||
|
implementation: *const Implementation,
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Provides a set of implementation-specific behaviors to a [FileAccess] instance.
|
||||||
|
///
|
||||||
|
pub const Implementation = struct {
|
||||||
|
close: fn (*anyopaque) void,
|
||||||
|
queryCursor: fn (*anyopaque) Error!u64,
|
||||||
|
queryLength: fn (*anyopaque) Error!u64,
|
||||||
|
read: fn (*anyopaque, []u8) Error!usize,
|
||||||
|
seek: fn (*anyopaque, u64) Error!void,
|
||||||
|
seekToEnd: fn (*anyopaque) Error!void,
|
||||||
|
skip: fn (*anyopaque, i64) Error!void,
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// [Error.FileInaccessible] is a generic catch-all for a [FileAccess] reference no longer
|
||||||
|
/// pointing to a file or the file becomming invalid for whatever reason.
|
||||||
|
///
|
||||||
|
pub const Error = error {
|
||||||
|
FileInaccessible,
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Close the file referenced by `file_access` on the main thread, invalidating the reference to
|
||||||
|
/// it and releasing any associated resources.
|
||||||
|
///
|
||||||
|
/// Freeing an invalid `file_access` has no effect on the file and logs a warning over the
|
||||||
|
/// wasted effort.
|
||||||
|
///
|
||||||
|
pub fn close(file_access: *FileAccess) void {
|
||||||
|
return file_access.implementation.close(file_access.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Attempts to query the current cursor position for the file referenced by `file_access`.
|
||||||
|
///
|
||||||
|
/// Returns the number of bytes into the file that the cursor is relative to its beginning or a
|
||||||
|
/// [Error] on failure.
|
||||||
|
///
|
||||||
|
pub fn queryCursor(file_access: *FileAccess) Error!u64 {
|
||||||
|
return file_access.implementation.queryCursor(file_access.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Attempts to query the current length for the file referenced by `file_access`.
|
||||||
|
///
|
||||||
|
/// Returns the current length of the file at the time of the operation or a [Error] if the file
|
||||||
|
/// failed to be queried.
|
||||||
|
///
|
||||||
|
pub fn queryLength(file_access: *FileAccess) Error!u64 {
|
||||||
|
return file_access.implementation.queryLength(file_access.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Attempts to read `file_access` from the its current position into `buffer`.
|
||||||
|
///
|
||||||
|
/// Returns the number of bytes that were available to be read, otherwise an [Error] on failure.
|
||||||
|
///
|
||||||
|
pub fn read(file_access: *FileAccess, buffer: []u8) Error!usize {
|
||||||
|
return file_access.implementation.read(file_access.context, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Attempts to seek `file_access` from the beginning of the file to `cursor` bytes.
|
||||||
|
///
|
||||||
|
/// Returns [Error] on failure.
|
||||||
|
///
|
||||||
|
pub fn seek(file_access: *FileAccess, cursor: u64) Error!void {
|
||||||
|
return file_access.implementation.seek(file_access.context, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Attempts to seek `file_access` to the end of the file.
|
||||||
|
///
|
||||||
|
/// Returns [Error] on failure.
|
||||||
|
///
|
||||||
|
pub fn seekToEnd(file_access: *FileAccess) Error!void {
|
||||||
|
return file_access.implementation.seekToEnd(file_access.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Attempts to seek `file_access` by `offset` from the current file position.
|
||||||
|
///
|
||||||
|
/// Returns [Error] on failure;
|
||||||
|
///
|
||||||
|
pub fn skip(file_access: *FileAccess, offset: i64) Error!void {
|
||||||
|
return file_access.implementation.skip(file_access.context, offset);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Opaque interface to a "writable" resource, such as a block device, memory buffer, or network
|
/// Opaque interface to a "writable" resource, such as a block device, memory buffer, or network
|
||||||
/// socket.
|
/// socket.
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub const io = @import("./io.zig");
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub const mem = @import("./mem.zig");
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub const meta = @import("./meta.zig");
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub const stack = @import("./stack.zig");
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
pub const table = @import("./table.zig");
|
Loading…
Reference in New Issue