Compare commits
	
		
			No commits in common. "3a0da39b3e284b91d0428c378f393e1ade405dd8" and "71ab200325f73ecb358f9cb2579da3bbed1168f3" have entirely different histories.
		
	
	
		
			3a0da39b3e
			...
			71ab200325
		
	
		
| @ -5,5 +5,4 @@ steps: | |||||||
| - name: build & test | - name: build & test | ||||||
|   image: euantorano/zig:0.9.1 |   image: euantorano/zig:0.9.1 | ||||||
|   commands: |   commands: | ||||||
|   - zig build test |   - zig test src/main.zig | ||||||
|   - $(find zig-cache -name test) main.zig |  | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							| @ -44,7 +44,7 @@ | |||||||
| 		{ | 		{ | ||||||
| 			"label": "Test", | 			"label": "Test", | ||||||
| 			"type": "shell", | 			"type": "shell", | ||||||
| 			"command": "$(find zig-cache -name test) src/main.zig", | 			"command": "zig test src/main.zig", | ||||||
| 			"group": { | 			"group": { | ||||||
| 				"kind": "test", | 				"kind": "test", | ||||||
| 				"isDefault": true | 				"isDefault": true | ||||||
|  | |||||||
							
								
								
									
										75
									
								
								src/io.zig
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								src/io.zig
									
									
									
									
									
								
							| @ -10,7 +10,7 @@ pub const Writer = struct { | |||||||
|     writeContext: fn (*anyopaque, []const u8) usize, |     writeContext: fn (*anyopaque, []const u8) usize, | ||||||
| 
 | 
 | ||||||
|     /// |     /// | ||||||
|     /// Radices supported by [writeInt]. |     /// | ||||||
|     /// |     /// | ||||||
|     pub const Radix = enum { |     pub const Radix = enum { | ||||||
|         binary, |         binary, | ||||||
| @ -79,45 +79,39 @@ pub const Writer = struct { | |||||||
|         const Int = @TypeOf(value); |         const Int = @TypeOf(value); | ||||||
|         const type_info = @typeInfo(Int); |         const type_info = @typeInfo(Int); | ||||||
| 
 | 
 | ||||||
|         switch (type_info) { |         if (type_info != .Int) @compileError("value must be of type int"); | ||||||
|             .Int => { |  | ||||||
|                 if (value == 0) return writer.writeByte('0'); |  | ||||||
| 
 | 
 | ||||||
|                 // TODO: Unhardcode this as it will break with large ints. |         if (value == 0) return writer.writeByte('0'); | ||||||
|                 var buffer = std.mem.zeroes([28]u8); |  | ||||||
|                 var buffer_count = @as(usize, 0); |  | ||||||
|                 var n1 = value; |  | ||||||
| 
 | 
 | ||||||
|                 if ((type_info.Int.signedness == .signed) and (value < 0)) { |         // TODO: Unhardcode this as it will break with large ints. | ||||||
|                     // Negative value. |         var buffer = std.mem.zeroes([28]u8); | ||||||
|                     n1 = -value; |         var buffer_count = @as(usize, 0); | ||||||
|                     buffer[0] = '-'; |         var n1 = value; | ||||||
|                     buffer_count += 1; |  | ||||||
|                 } |  | ||||||
| 
 | 
 | ||||||
|                 while (n1 != 0) { |         if ((type_info.Int.signedness == .signed) and (value < 0)) { | ||||||
|                     const base = @enumToInt(radix); |             // Negative value. | ||||||
| 
 |             n1 = -value; | ||||||
|                     buffer[buffer_count] = @intCast(u8, (n1 % base) + '0'); |             buffer[0] = '-'; | ||||||
|                     n1 = (n1 / base); |             buffer_count += 1; | ||||||
|                     buffer_count += 1; |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 for (buffer[0 .. (buffer_count / 2)]) |_, i| |  | ||||||
|                     std.mem.swap(u8, &buffer[i], &buffer[buffer_count - i - 1]); |  | ||||||
| 
 |  | ||||||
|                 return (writer.write(buffer[0 .. buffer_count]) == buffer_count); |  | ||||||
|             }, |  | ||||||
| 
 |  | ||||||
|             // Cast comptime int into known-size integer and try again. |  | ||||||
|             .ComptimeInt => return writer. |  | ||||||
|                 writeInt(radix, @intCast(std.math.IntFittingRange(value, value), value)), |  | ||||||
| 
 |  | ||||||
|             else => @compileError("value must be of type int"), |  | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         while (n1 != 0) { | ||||||
|  |             const base = @enumToInt(radix); | ||||||
|  | 
 | ||||||
|  |             buffer[buffer_count] = @intCast(u8, (n1 % base) + '0'); | ||||||
|  |             n1 = (n1 / base); | ||||||
|  |             buffer_count += 1; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (buffer[0 .. (buffer_count / 2)]) |_, i| | ||||||
|  |             std.mem.swap(u8, &buffer[i], &buffer[buffer_count - i - 1]); | ||||||
|  | 
 | ||||||
|  |         return (writer.write(buffer[0 .. buffer_count]) == buffer_count); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | var null_context = @as(usize, 0); | ||||||
|  | 
 | ||||||
| /// | /// | ||||||
| /// Writer that silently throws consumed data away and never fails. | /// Writer that silently throws consumed data away and never fails. | ||||||
| /// | /// | ||||||
| @ -125,10 +119,13 @@ pub const Writer = struct { | |||||||
| /// sent somewhere for whatever reason. | /// sent somewhere for whatever reason. | ||||||
| /// | /// | ||||||
| pub const null_writer = Writer{ | pub const null_writer = Writer{ | ||||||
|     .context = undefined, |     .context = (&null_context), | ||||||
|  | 
 | ||||||
|  |     .operation = struct { | ||||||
|  |         fn write(context: *anyopaque, buffer: []const u8) usize { | ||||||
|  |             // Validate context canary value. | ||||||
|  |             std.debug.assert(@ptrCast(*usize, @alignCast(@alignOf(usize), context)).* == 0); | ||||||
| 
 | 
 | ||||||
|     .writeContext = struct { |  | ||||||
|         fn write(_: *anyopaque, buffer: []const u8) usize { |  | ||||||
|             return buffer.len; |             return buffer.len; | ||||||
|         } |         } | ||||||
|     }.write, |     }.write, | ||||||
| @ -140,9 +137,9 @@ test { | |||||||
|     { |     { | ||||||
|         const sequence = "foo"; |         const sequence = "foo"; | ||||||
| 
 | 
 | ||||||
|         try testing.expectEqual(null_writer.write(sequence), sequence.len); |         testing.expectEqual(null_writer.write(sequence), sequence.len); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     try testing.expect(null_writer.writeByte(0)); |     testing.expect(null_writer.writeByte(0)); | ||||||
|     try testing.expect(null_writer.writeInt(.decimal, 420)); |     testing.expect(null_writer.writeInt(.decimal, 420)); | ||||||
| } | } | ||||||
|  | |||||||
| @ -15,10 +15,7 @@ pub fn main() anyerror!void { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| test { | test { | ||||||
|     _ = io; | 
 | ||||||
|     _ = stack; |  | ||||||
|     _ = std; |  | ||||||
|     _ = sys; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn run(event_loop: *sys.EventLoop, graphics: *sys.GraphicsContext) anyerror!void { | fn run(event_loop: *sys.EventLoop, graphics: *sys.GraphicsContext) anyerror!void { | ||||||
| @ -41,7 +38,7 @@ fn run(event_loop: *sys.EventLoop, graphics: *sys.GraphicsContext) anyerror!void | |||||||
|         if ((try event_loop.readFile(file_access, buffer)) != file_size) |         if ((try event_loop.readFile(file_access, buffer)) != file_size) | ||||||
|             return error.ScriptLoadFailure; |             return error.ScriptLoadFailure; | ||||||
| 
 | 
 | ||||||
|         event_loop.log(.debug, buffer); |         event_loop.log(buffer); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     while (graphics.poll()) |_| { |     while (graphics.poll()) |_| { | ||||||
|  | |||||||
| @ -91,7 +91,7 @@ pub const FixedPushError = error { | |||||||
|     Overflow, |     Overflow, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| test { | test "fixed stack" { | ||||||
|     const testing = std.testing; |     const testing = std.testing; | ||||||
|     var buffer = std.mem.zeroes([4]u8); |     var buffer = std.mem.zeroes([4]u8); | ||||||
|     var stack = Fixed(u8){.buffer = &buffer}; |     var stack = Fixed(u8){.buffer = &buffer}; | ||||||
|  | |||||||
							
								
								
									
										104
									
								
								src/sys.zig
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								src/sys.zig
									
									
									
									
									
								
							| @ -8,7 +8,7 @@ const stack = @import("./stack.zig"); | |||||||
| const std = @import("std"); | const std = @import("std"); | ||||||
| 
 | 
 | ||||||
| /// | /// | ||||||
| /// A thread-safe platform abstraction over multiplexing system I/O processing and event handling. | /// | ||||||
| /// | /// | ||||||
| pub const EventLoop = opaque { | pub const EventLoop = opaque { | ||||||
|     /// |     /// | ||||||
| @ -23,7 +23,7 @@ pub const EventLoop = opaque { | |||||||
|             exit, |             exit, | ||||||
| 
 | 
 | ||||||
|             close: struct { |             close: struct { | ||||||
|                 file_access: *FileAccess, |                 file_system_path: *FileAccess, | ||||||
|             }, |             }, | ||||||
| 
 | 
 | ||||||
|             log: struct { |             log: struct { | ||||||
| @ -33,7 +33,7 @@ pub const EventLoop = opaque { | |||||||
| 
 | 
 | ||||||
|             open: struct { |             open: struct { | ||||||
|                 mode: OpenMode, |                 mode: OpenMode, | ||||||
|                 file_system_path: *const FileSystem.Path, |                 path: *const FileSystem.Path, | ||||||
|                 result: OpenError!*FileAccess = error.NotFound, |                 result: OpenError!*FileAccess = error.NotFound, | ||||||
|             }, |             }, | ||||||
| 
 | 
 | ||||||
| @ -138,15 +138,13 @@ pub const EventLoop = opaque { | |||||||
|     /// |     /// | ||||||
|     /// Closes access to the file referenced by `file_access` via `event_loop`. |     /// Closes access to the file referenced by `file_access` via `event_loop`. | ||||||
|     /// |     /// | ||||||
|     /// *Note* that nothing happens to `file_access` if it is already closed. |  | ||||||
|     /// |  | ||||||
|     pub fn close(event_loop: *EventLoop, file_access: *FileAccess) void { |     pub fn close(event_loop: *EventLoop, file_access: *FileAccess) void { | ||||||
|         var file_system_message = FileSystemMessage{ |         var message = FileSystemMessage{ | ||||||
|             .frame = @frame(), |             .frame = @frame(), | ||||||
|             .request = .{.close = .{.file_access = file_access}}, |             .request = .{.close = .{.file_access = file_access}}, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         suspend event_loop.enqueueFileSystemMessage(&file_system_message); |         suspend event_loop.enqueueFileSystemMessage(&message); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// |     /// | ||||||
| @ -176,7 +174,7 @@ pub const EventLoop = opaque { | |||||||
|     /// *Note* that `message` is not guaranteed to be partly, wholely, or at all written. |     /// *Note* that `message` is not guaranteed to be partly, wholely, or at all written. | ||||||
|     /// |     /// | ||||||
|     pub fn log(event_loop: *EventLoop, kind: LogKind, message: []const u8) void { |     pub fn log(event_loop: *EventLoop, kind: LogKind, message: []const u8) void { | ||||||
|         var file_system_message = FileSystemMessage{ |         var message = FileSystemMessage{ | ||||||
|             .frame = @frame(), |             .frame = @frame(), | ||||||
| 
 | 
 | ||||||
|             .request = .{.log = .{ |             .request = .{.log = .{ | ||||||
| @ -185,7 +183,7 @@ pub const EventLoop = opaque { | |||||||
|             }}, |             }}, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         suspend event_loop.enqueueFileSystemMessage(&file_system_message); |         suspend event_loop.enqueueFileSystemMessage(&message); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// |     /// | ||||||
| @ -201,26 +199,24 @@ pub const EventLoop = opaque { | |||||||
|     pub fn open(event_loop: *EventLoop, mode: OpenMode, |     pub fn open(event_loop: *EventLoop, mode: OpenMode, | ||||||
|         file_system_path: FileSystem.Path) OpenError!*FileAccess { |         file_system_path: FileSystem.Path) OpenError!*FileAccess { | ||||||
| 
 | 
 | ||||||
|         var file_system_message = FileSystemMessage{ |         var message = FileSystemMessage{ | ||||||
|             .frame = @frame(), |             .frame = @frame(), | ||||||
| 
 | 
 | ||||||
|             .request = .{.open = .{ |             .request = .{ | ||||||
|                 .mode = mode, |                 .open = .{ | ||||||
|                 .file_system_path = &file_system_path, |                     .mode = mode, | ||||||
|             }}, |                     .file_system_path = &file_system_path, | ||||||
|  |                 }, | ||||||
|  |             }, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         suspend event_loop.enqueueFileSystemMessage(&file_system_message); |         suspend event_loop.enqueueFileSystemMessage(&message); | ||||||
| 
 | 
 | ||||||
|         return file_system_message.request.open.result; |         return message.request.open.result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// |     /// | ||||||
|     /// [FileSystemMessage] processing function used by a dedicated worker thread, where `data` is |  | ||||||
|     /// a type-erased reference to a [EventLoop]. |  | ||||||
|     /// |     /// | ||||||
|     /// The processor returns `0` if it exited normally or any other value if an erroneous exit |  | ||||||
|     /// occured. |  | ||||||
|     /// |     /// | ||||||
|     fn processFileSystemMessages(data: ?*anyopaque) callconv(.C) c_int { |     fn processFileSystemMessages(data: ?*anyopaque) callconv(.C) c_int { | ||||||
|         const implementation = Implementation.cast(@ptrCast(*EventLoop, data orelse unreachable)); |         const implementation = Implementation.cast(@ptrCast(*EventLoop, data orelse unreachable)); | ||||||
| @ -270,23 +266,20 @@ pub const EventLoop = opaque { | |||||||
|                     }, |                     }, | ||||||
| 
 | 
 | ||||||
|                     .close => |*close_request| { |                     .close => |*close_request| { | ||||||
|                         // TODO: Use this result somehow. |                         // Don't care if this doesn't work. | ||||||
|                         _ = ext.SDL_RWclose(@ptrCast(*ext.SDL_RWops, @alignCast( |                         _ = ext.SDL_RWclose(@ptrCast(*ext.SDL_RWops, @alignCast( | ||||||
|                                 @alignOf(ext.SDL_RWops), close_request.file_access))); |                                 @alignOf(ext.SDL_RWops), close_request.file_access))); | ||||||
|                     }, |                     }, | ||||||
| 
 | 
 | ||||||
|                     .read_file => |read_request| { |                     .read_file => |read_request| { | ||||||
|                         // TODO: Implement. |  | ||||||
|                         _ = read_request; |                         _ = read_request; | ||||||
|                     }, |                     }, | ||||||
| 
 | 
 | ||||||
|                     .seek_file => |seek_request| { |                     .seek_file => |seek_request| { | ||||||
|                         // TODO: Implement. |  | ||||||
|                         _ = seek_request; |                         _ = seek_request; | ||||||
|                     }, |                     }, | ||||||
| 
 | 
 | ||||||
|                     .tell_file => |tell_request| { |                     .tell_file => |tell_request| { | ||||||
|                         // TODO: Implement. |  | ||||||
|                         _ = tell_request; |                         _ = tell_request; | ||||||
|                     }, |                     }, | ||||||
|                 } |                 } | ||||||
| @ -311,45 +304,29 @@ pub const EventLoop = opaque { | |||||||
|     pub fn readFile(event_loop: *EventLoop, file_access: *FileAccess, |     pub fn readFile(event_loop: *EventLoop, file_access: *FileAccess, | ||||||
|         buffer: []const u8) FileError!usize { |         buffer: []const u8) FileError!usize { | ||||||
| 
 | 
 | ||||||
|         var file_system_message = FileSystemMessage{ |         var message = FileSystemMessage{ | ||||||
|             .frame = @frame(), |             .frame = @frame(), | ||||||
| 
 | 
 | ||||||
|             .request = .{.read_file = .{ |             .request = .{ | ||||||
|                 .file_access = file_access, |                 .read_file = .{ | ||||||
|                 .buffer = buffer, |                     .file_access = file_access, | ||||||
|             }}, |                     .buffer = buffer, | ||||||
|  |                 }, | ||||||
|  |             }, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         suspend event_loop.enqueueFileSystemMessage(&file_system_message); |         suspend event_loop.enqueueFileSystemMessage(&message); | ||||||
| 
 | 
 | ||||||
|         return file_system_message.request.read_file.result; |         return message.request.read_file.result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// |     /// | ||||||
|     /// Attempts to tell the current file 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 |  | ||||||
|     /// [FileError] if the file failed to be queried. |  | ||||||
|     /// |  | ||||||
|     pub fn queryFile(event_loop: *EventLoop, file_access: *FileAccess) FileError!usize { |  | ||||||
|         var file_system_message = FileSystemMessage{ |  | ||||||
|             .frame = @frame(), |  | ||||||
|             .request = .{.tell_file = .{.file_access = file_access}}, |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         suspend event_loop.enqueueFileSystemMessage(&file_system_message); |  | ||||||
| 
 |  | ||||||
|         return file_system_message.request.tell_file.result; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /// |  | ||||||
|     /// Attempts to seek the file cursor through the file referenced by `file_access` from `origin` |  | ||||||
|     /// to `offset` via `event_loop`, returning a [FileError] if the file failed to be sought. |  | ||||||
|     /// |     /// | ||||||
|     pub fn seekFile(event_loop: *EventLoop, file_access: *FileAccess, |     pub fn seekFile(event_loop: *EventLoop, file_access: *FileAccess, | ||||||
|         origin: SeekOrigin, offset: usize) FileError!void { |         origin: SeekOrigin, offset: usize) FileError!void { | ||||||
| 
 | 
 | ||||||
|         var file_system_message = FileSystemMessage{ |         var message = FileSystemMessage{ | ||||||
|             .frame = @frame(), |             .frame = @frame(), | ||||||
| 
 | 
 | ||||||
|             .request = .{ |             .request = .{ | ||||||
| @ -361,9 +338,23 @@ pub const EventLoop = opaque { | |||||||
|             }, |             }, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         suspend event_loop.enqueueFileSystemMessage(&file_system_message); |         suspend event_loop.enqueueFileSystemMessage(&message); | ||||||
| 
 | 
 | ||||||
|         return file_system_message.request.seek_file.result; |         return message.request.seek_file.result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /// | ||||||
|  |     /// | ||||||
|  |     /// | ||||||
|  |     pub fn tellFile(event_loop: *EventLoop, file_access: *FileAccess) FileError!usize { | ||||||
|  |         var message = FileSystemMessage{ | ||||||
|  |             .frame = @frame(), | ||||||
|  |             .request = .{.tell_file = .{.file_access = file_access}}, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         suspend event_loop.enqueueFileSystemMessage(&message); | ||||||
|  | 
 | ||||||
|  |         return message.request.tell_file.result; | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -377,11 +368,11 @@ pub const FileAccess = opaque { | |||||||
|     /// |     /// | ||||||
|     pub fn size(file_access: *FileAccess, event_loop: *EventLoop) FileError!usize { |     pub fn size(file_access: *FileAccess, event_loop: *EventLoop) FileError!usize { | ||||||
|         // Save cursor to return to it later. |         // Save cursor to return to it later. | ||||||
|         const origin_cursor = try event_loop.queryFile(file_access); |         const origin_cursor = try event_loop.tellFile(file_access); | ||||||
| 
 | 
 | ||||||
|         try event_loop.seekFile(file_access, .tail, 0); |         try event_loop.seekFile(file_access, .tail, 0); | ||||||
| 
 | 
 | ||||||
|         const ending_cursor = try event_loop.queryFile(file_access); |         const ending_cursor = try event_loop.tellFile(file_access); | ||||||
| 
 | 
 | ||||||
|         // Return to original cursor. |         // Return to original cursor. | ||||||
|         try event_loop.seekFile(file_access, .head, origin_cursor); |         try event_loop.seekFile(file_access, .head, origin_cursor); | ||||||
| @ -400,15 +391,14 @@ pub const FileError = error { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// | /// | ||||||
| /// Platform-agnostic mechanism for working with an abstraction of the underlying file-system(s) | /// | ||||||
| /// available to the application in a sandboxed environment. |  | ||||||
| /// | /// | ||||||
| pub const FileSystem = enum { | pub const FileSystem = enum { | ||||||
|     data, |     data, | ||||||
|     user, |     user, | ||||||
| 
 | 
 | ||||||
|     /// |     /// | ||||||
|     /// Platform-agnostic mechanism for referencing files and directories on a [FileSystem]. |     /// Platform-agnostic mechanism for referencing files and directories on a [FileSystem] | ||||||
|     /// |     /// | ||||||
|     pub const Path = struct { |     pub const Path = struct { | ||||||
|         file_system: FileSystem, |         file_system: FileSystem, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user