batman
This commit is contained in:
commit
0ea7d8b7ee
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
zig-out/
|
||||
zig-cache
|
70
build.zig
Normal file
70
build.zig
Normal file
@ -0,0 +1,70 @@
|
||||
const std = @import("std");
|
||||
|
||||
// Although this function looks imperative, note that its job is to
|
||||
// declaratively construct a build graph that will be executed by an external
|
||||
// runner.
|
||||
pub fn build(b: *std.Build) void {
|
||||
// Standard target options allows the person running `zig build` to choose
|
||||
// what target to build for. Here we do not override the defaults, which
|
||||
// means any target is allowed, and the default is native. Other options
|
||||
// for restricting supported target set are available.
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
// Standard optimization options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
||||
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "ebook-reader",
|
||||
// In this case the main source file is merely a path, however, in more
|
||||
// complicated build scripts, this could be a generated file.
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
// This declares intent for the executable to be installed into the
|
||||
// standard location when the user invokes the "install" step (the default
|
||||
// step when running `zig build`).
|
||||
b.installArtifact(exe);
|
||||
|
||||
// This *creates* a Run step in the build graph, to be executed when another
|
||||
// step is evaluated that depends on it. The next line below will establish
|
||||
// such a dependency.
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
|
||||
// By making the run step depend on the install step, it will be run from the
|
||||
// installation directory rather than directly from within the cache directory.
|
||||
// This is not necessary, however, if the application depends on other installed
|
||||
// files, this ensures they will be present and in the expected location.
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
|
||||
// This allows the user to pass arguments to the application in the build
|
||||
// command itself, like this: `zig build run -- arg1 arg2 etc`
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
}
|
||||
|
||||
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||
// and can be selected like this: `zig build run`
|
||||
// This will evaluate the `run` step rather than the default, which is "install".
|
||||
const run_step = b.step("run", "Run the app");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
|
||||
// Creates a step for unit testing. This only builds the test executable
|
||||
// but does not run it.
|
||||
const unit_tests = b.addTest(.{
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const run_unit_tests = b.addRunArtifact(unit_tests);
|
||||
|
||||
// Similar to creating the run step earlier, this exposes a `test` step to
|
||||
// the `zig build --help` menu, providing a way for the user to request
|
||||
// running the unit tests.
|
||||
const test_step = b.step("test", "Run unit tests");
|
||||
test_step.dependOn(&run_unit_tests.step);
|
||||
}
|
78
flake.lock
Normal file
78
flake.lock
Normal file
@ -0,0 +1,78 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1661151577,
|
||||
"narHash": "sha256-++S0TuJtuz9IpqP8rKktWyHZKpgdyrzDFUXVY07MTRI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "54060e816971276da05970a983487a25810c38a7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"zig": "zig"
|
||||
}
|
||||
},
|
||||
"zig": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1684670828,
|
||||
"narHash": "sha256-e3HSmT9ufQ0WZYh6hOPx87dg/4jjLoJLl6zAEzev07E=",
|
||||
"owner": "mitchellh",
|
||||
"repo": "zig-overlay",
|
||||
"rev": "22a39bd5ce8f8b0fdec3049ca5bfb54c748380bd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "mitchellh",
|
||||
"repo": "zig-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
9
flake.nix
Normal file
9
flake.nix
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
description = "A very basic flake";
|
||||
|
||||
inputs.zig.url = "github:mitchellh/zig-overlay";
|
||||
|
||||
outputs = { self, zig, ... }: {
|
||||
packages.x86_64-linux.zig = zig.packages.x86_64-linux.master;
|
||||
};
|
||||
}
|
128
src/main.zig
Normal file
128
src/main.zig
Normal file
@ -0,0 +1,128 @@
|
||||
const std = @import("std");
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
const stderr = std.io.getStdErr().writer();
|
||||
|
||||
fn print(comptime str: []const u8, params: anytype) void {
|
||||
stdout.print(str ++ "\n", params) catch {};
|
||||
}
|
||||
|
||||
fn pErr(comptime str: []const u8, params: anytype) void {
|
||||
stderr.print(str ++ "\n", params) catch {};
|
||||
}
|
||||
|
||||
fn exit(comptime str: []const u8, params: anytype, exitCode: u8) void {
|
||||
pErr(str, params);
|
||||
std.os.exit(exitCode);
|
||||
}
|
||||
|
||||
fn usage() void {
|
||||
pErr("reader <path>", .{});
|
||||
exit("", .{}, 1);
|
||||
}
|
||||
|
||||
const LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
|
||||
const ZipFileHeader = struct {
|
||||
version: u16,
|
||||
general: u16,
|
||||
compression_method: u16,
|
||||
last_mod_time: u16,
|
||||
last_mod_date: u16,
|
||||
crc_32: u32,
|
||||
compressed_size: u32,
|
||||
uncompressed_size: u32,
|
||||
file_name_length: u16,
|
||||
extra_field_length: u16,
|
||||
|
||||
file_name: []u8,
|
||||
extra_field: []u8,
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
fn init(allocator: std.mem.Allocator, reader: std.fs.File.Reader) !Self {
|
||||
if (try reader.readInt(u32, .Big) == LOCAL_FILE_HEADER_SIGNATURE) {
|
||||
return error.InvalidError;
|
||||
}
|
||||
|
||||
var self = Self{
|
||||
.allocator = allocator,
|
||||
.version = try reader.readInt(u16, .Big),
|
||||
.general = try reader.readInt(u16, .Big),
|
||||
.compression_method = try reader.readInt(u16, .Big),
|
||||
.last_mod_time = try reader.readInt(u16, .Big),
|
||||
.last_mod_date = try reader.readInt(u16, .Big),
|
||||
.crc_32 = try reader.readInt(u32, .Big),
|
||||
.compressed_size = try reader.readInt(u32, .Big),
|
||||
.uncompressed_size = try reader.readInt(u32, .Big),
|
||||
.file_name_length = try reader.readInt(u16, .Big),
|
||||
.extra_field_length = try reader.readInt(u16, .Big),
|
||||
.file_name = undefined,
|
||||
.extra_field = undefined,
|
||||
};
|
||||
|
||||
self.file_name = try allocator.alloc(u8, self.file_name_length);
|
||||
self.extra_field = try allocator.alloc(u8, self.extra_field_length);
|
||||
|
||||
_ = try reader.read(self.file_name);
|
||||
_ = try reader.read(self.extra_field);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
fn deinit(self: *Self) void {
|
||||
self.allocator.free(self.file_name);
|
||||
self.allocator.free(self.extra_field);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
var args = std.process.args();
|
||||
|
||||
var filePath: ?[]const u8 = null;
|
||||
|
||||
// Skip the current path
|
||||
_ = args.next();
|
||||
while (args.next()) |arg| {
|
||||
if (filePath == null) {
|
||||
filePath = arg;
|
||||
} else {
|
||||
pErr("Invalid argument: {s}", .{arg});
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (filePath == null) {
|
||||
pErr("File path not provided. Please provide a path", .{});
|
||||
usage();
|
||||
}
|
||||
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
|
||||
var allocator = gpa.allocator();
|
||||
|
||||
var book_path = try std.fs.realpathAlloc(allocator, filePath.?);
|
||||
defer allocator.free(book_path);
|
||||
|
||||
var file = std.fs.openFileAbsolute(book_path, .{}) catch |err| {
|
||||
exit("Please provide a file path! Error: {?}", .{err}, 1);
|
||||
return err;
|
||||
};
|
||||
defer file.close();
|
||||
|
||||
var stat = try file.stat();
|
||||
|
||||
if (stat.kind != .File) {
|
||||
exit("Please provide a valid file", .{}, 1);
|
||||
}
|
||||
|
||||
var reader = file.reader();
|
||||
|
||||
var first_file = try ZipFileHeader.init(allocator, reader);
|
||||
defer first_file.deinit();
|
||||
|
||||
print("G: {}", .{first_file.file_name_length});
|
||||
print("T: {s}", .{first_file.file_name});
|
||||
print("O: {s}", .{first_file.extra_field});
|
||||
}
|
Loading…
Reference in New Issue
Block a user