Remove Oar as a dedicated module
This commit is contained in:
		
							parent
							
								
									b4816a34f6
								
							
						
					
					
						commit
						5a913ef0f8
					
				
							
								
								
									
										10
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							| @ -10,15 +10,7 @@ | ||||
| 			"valuesFormatting": "parseText", | ||||
| 			"preLaunchTask": "Build Debug", | ||||
| 		}, | ||||
| 		{ | ||||
| 			"name": "Oar", | ||||
| 			"type": "gdb", | ||||
| 			"request": "launch", | ||||
| 			"target": "${workspaceFolder}/zig-out/bin/oar", | ||||
| 			"cwd": "${workspaceRoot}", | ||||
| 			"valuesFormatting": "parseText", | ||||
| 			"preLaunchTask": "Build Debug", | ||||
| 		}, | ||||
| 
 | ||||
| 		{ | ||||
| 			"name": "Test", | ||||
| 			"type": "gdb", | ||||
|  | ||||
							
								
								
									
										253
									
								
								src/oar/main.zig
									
									
									
									
									
								
							
							
						
						
									
										253
									
								
								src/oar/main.zig
									
									
									
									
									
								
							| @ -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(©_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; | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user