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. | ||||||
							
								
								
									
										25
									
								
								src/ona/main.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/ona/main.zig
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | 
 | ||||||
|  | /// | ||||||
|  | /// | ||||||
|  | /// | ||||||
|  | pub const io = @import("./io.zig"); | ||||||
|  | 
 | ||||||
|  | /// | ||||||
|  | /// | ||||||
|  | /// | ||||||
|  | pub const mem = @import("./mem.zig"); | ||||||
|  | 
 | ||||||
|  | /// | ||||||
| 
					
					kayomn marked this conversation as resolved
					
						
						
							Outdated
						
					
				 | |||||||
|  | /// | ||||||
|  | /// | ||||||
|  | pub const meta = @import("./meta.zig"); | ||||||
|  | 
 | ||||||
|  | /// | ||||||
|  | /// | ||||||
|  | /// | ||||||
|  | pub const stack = @import("./stack.zig"); | ||||||
|  | 
 | ||||||
|  | /// | ||||||
|  | /// | ||||||
|  | /// | ||||||
|  | pub const table = @import("./table.zig"); | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	
Missing documentation comment.