diff --git a/build.zig b/build.zig index b899536..443992c 100644 --- a/build.zig +++ b/build.zig @@ -3,19 +3,26 @@ const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const exe = b.addExecutable(.{ - .name = "ziglets", + const exe_root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, + }); + const exe = b.addExecutable(.{ + .name = "ziglets", + .root_module = exe_root_module, .version = std.SemanticVersion.parse("0.1.0") catch null, }); - b.installArtifact(exe); // Add test support - const exe_unit_tests = b.addTest(.{ + b.installArtifact(exe); + + const test_root_module = b.createModule(.{ .root_source_file = b.path("src/tests.zig"), .target = target, .optimize = optimize, }); + const exe_unit_tests = b.addTest(.{ + .root_module = test_root_module, + }); const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests); diff --git a/src/main.zig b/src/main.zig index 78962c5..2ef1ca8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -47,8 +47,10 @@ pub const commands = [_]Command{ }; fn helpHandler(_: std.mem.Allocator, _: []const []const u8) !void { - const stdout = std.io.getStdOut().writer(); - try stdout.print( + const io = std.Io.Threaded.global_single_threaded.io(); + var stdout_buffer: [0]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); + try stdout.interface.print( \\ziglets \\ \\Available commands: @@ -56,34 +58,31 @@ fn helpHandler(_: std.mem.Allocator, _: []const []const u8) !void { , .{}); for (commands) |cmd| { // Print the command name, padded to 10 chars, and its description - try stdout.print(" {s: <12} {s}\n", .{ cmd.name, cmd.description }); + try stdout.interface.print(" {s: <12} {s}\n", .{ cmd.name, cmd.description }); } - try stdout.print("\n", .{}); + try stdout.interface.print("\n", .{}); } -pub fn main() !void { +pub fn main(init: std.process.Init.Minimal) !void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); - var args_iter = try std.process.argsWithAllocator(arena.allocator()); - var args = std.ArrayList([]const u8).init(arena.allocator()); - - while (true) { - const arg = args_iter.next(); - if (arg == null) break; - try args.append(arg.?); + const raw_args = try std.process.Args.toSlice(init.args, arena.allocator()); + const args = try arena.allocator().alloc([]const u8, raw_args.len); + for (raw_args, 0..) |arg, i| { + args[i] = arg; } - if (args.items.len < 2) { + if (args.len < 2) { std.debug.print("Usage: ziglets \n", .{}); std.debug.print("Try 'ziglets help' for more information.\n", .{}); return error.InvalidArguments; } - const command = args.items[1]; + const command = args[1]; for (commands) |cmd| { if (std.mem.eql(u8, command, cmd.name)) { - try cmd.handler(arena.allocator(), args.items[2..]); + try cmd.handler(arena.allocator(), args[2..]); return; } } diff --git a/src/ziglets/calculator.zig b/src/ziglets/calculator.zig index 01c9634..b8b4c65 100644 --- a/src/ziglets/calculator.zig +++ b/src/ziglets/calculator.zig @@ -10,7 +10,7 @@ const State = struct { }; // Print the calculator display -fn printDisplay(state: *State, writer: anytype) !void { +fn printDisplay(state: *State, writer: *std.Io.Writer) !void { if (state.entering_operand) { try writer.print("\r{d:.8} ", .{state.operand}); } else { @@ -67,16 +67,6 @@ const RawMode = if (builtin.os.tag == .windows) struct { const posix = std.posix; // Definizione manuale dei flag POSIX se non presenti in std.posix - const ICANON: u32 = 0x0002; // 0b0000000000000010 - const ECHO: u32 = 0x0008; // 0b0000000000001000 - const ISIG: u32 = 0x0001; // 0b0000000000000001 - const IEXTEN: u32 = 0x8000; // 0b1000000000000000 - const IXON: u32 = 0x0400; // 0b0000010000000000 - const ICRNL: u32 = 0x0100; // 0b0000000100000000 - const BRKINT: u32 = 0x0002; // 0b0000000000000010 - const INPCK: u32 = 0x0010; // 0b0000000001000000 - const ISTRIP: u32 = 0x0020; // 0b0000000010000000 - const OPOST: u32 = 0x0001; // 0b0000000000000001 const VMIN: u32 = 6; // 0b0000000000010110 const VTIME: u32 = 5; // 0b0000000000010101 @@ -88,9 +78,16 @@ const RawMode = if (builtin.os.tag == .windows) struct { var raw = original_termios; // Disabilita echo, modalità canonica e segnali - raw.lflag = @bitCast(@as(u32, @bitCast(raw.lflag)) & ~@as(u32, ICANON | ECHO | ISIG | IEXTEN)); - raw.iflag = @bitCast(@as(u32, @bitCast(raw.iflag)) & ~@as(u32, IXON | ICRNL | BRKINT | INPCK | ISTRIP)); - raw.oflag = @bitCast(@as(u32, @bitCast(raw.oflag)) & ~@as(u32, OPOST)); + raw.lflag.ICANON = false; + raw.lflag.ECHO = false; + raw.lflag.ISIG = false; + raw.lflag.IEXTEN = false; + raw.iflag.IXON = false; + raw.iflag.ICRNL = false; + raw.iflag.BRKINT = false; + raw.iflag.INPCK = false; + raw.iflag.ISTRIP = false; + raw.oflag.OPOST = false; raw.cc[VMIN] = 1; raw.cc[VTIME] = 0; @@ -103,9 +100,12 @@ const RawMode = if (builtin.os.tag == .windows) struct { }; pub fn run(_: std.mem.Allocator, _: []const []const u8) !void { + const io = std.Io.Threaded.global_single_threaded.io(); var state = State{}; - var stdin = std.io.getStdIn().reader(); - var stdout = std.io.getStdOut().writer(); + var stdin_buffer: [128]u8 = undefined; + var stdout_buffer: [0]u8 = undefined; + var stdin = std.Io.File.stdin().reader(io, &stdin_buffer); + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); // Abilita la modalità raw per l'input istantaneo try RawMode.enable(); @@ -113,25 +113,21 @@ pub fn run(_: std.mem.Allocator, _: []const []const u8) !void { RawMode.disable() catch {}; } - try stdout.print("Calculator (press Q to exit)\n", .{}); - try printDisplay(&state, stdout); + try stdout.interface.print("Calculator (press Q to exit)\n", .{}); + try printDisplay(&state, &stdout.interface); while (true) { - var buf: [1]u8 = undefined; - // Leggiamo un singolo carattere (ora senza bisogno di premere Enter) - const bytes_read = stdin.read(&buf) catch |err| { - try stdout.print("\nError durante la lettura: {s}\n", .{@errorName(err)}); - return err; + const c = stdin.interface.takeByte() catch |err| switch (err) { + error.EndOfStream => return, + error.ReadFailed => { + try stdout.interface.print("\nError durante la lettura: {s}\n", .{@errorName(stdin.err.?)}); + return stdin.err.?; + }, }; - // Se non abbiamo letto nulla, continuiamo - if (bytes_read == 0) continue; - - const c = buf[0]; - if (c == 'q' or c == 'Q') { // Q key - try stdout.print("\nBye!\n", .{}); + try stdout.interface.print("\nBye!\n", .{}); return; } @@ -156,7 +152,7 @@ pub fn run(_: std.mem.Allocator, _: []const []const u8) !void { else => digit = 0, // Should not happen due to the check above } state.operand = state.operand * 10 + digit; - try printDisplay(&state, stdout); + try printDisplay(&state, &stdout.interface); } else if (c == '.' or c == ',') { // Decimal point not implemented for simplicity } else if (c == '+' or c == '-' or c == '*' or c == '/') { @@ -170,23 +166,23 @@ pub fn run(_: std.mem.Allocator, _: []const []const u8) !void { state.operand = 0; } state.op = c; - try printDisplay(&state, stdout); + try printDisplay(&state, &stdout.interface); } else if (c == '=' or c == '\r' or c == '\n') { if (state.op != null and state.entering_operand) { applyOp(&state); state.op = null; state.entering_operand = false; state.operand = 0; - try printDisplay(&state, stdout); + try printDisplay(&state, &stdout.interface); } } else if (c == 8 or c == 127) { // Backspace if (state.entering_operand) { state.operand = @floor(state.operand / 10); - try printDisplay(&state, stdout); + try printDisplay(&state, &stdout.interface); } } else if (c == 'c' or c == 'C') { // Clear state = State{}; - try printDisplay(&state, stdout); + try printDisplay(&state, &stdout.interface); } } } diff --git a/src/ziglets/clock.zig b/src/ziglets/clock.zig index 88036af..bf19940 100644 --- a/src/ziglets/clock.zig +++ b/src/ziglets/clock.zig @@ -8,19 +8,21 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void { _ = allocator; // allocator not used in this implementation _ = args; // args not used in this implementation - const stdout = std.io.getStdOut().writer(); + const io = std.Io.Threaded.global_single_threaded.io(); + var stdout_buffer: [0]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); // Print initial message - try stdout.print("Terminal Clock - Press Ctrl+C to exit\n\n", .{}); + try stdout.interface.print("Terminal Clock - Press Ctrl+C to exit\n\n", .{}); // Simple implementation that works on all platforms while (true) { // Clear the current line and move cursor to beginning - try stdout.print("\r", .{}); + try stdout.interface.print("\r", .{}); // Get current time - const timestamp = std.time.timestamp(); - const epoch_seconds = @as(u64, @intCast(timestamp)); + const timestamp = std.Io.Clock.real.now(io); + const epoch_seconds = @as(u64, @intCast(timestamp.toSeconds())); // Convert to broken down time (UTC) const epoch_day = epoch_seconds / std.time.s_per_day; @@ -36,10 +38,13 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void { const month_day = calculateMonthDay(day_of_year, isLeapYear(year)); // Display formatted time and date with emojis - try stdout.print("{d:0>4}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2}:{d:0>2} UTC", .{ year, month_day.month, month_day.day, hours, minutes, seconds }); + try stdout.interface.print("{d:0>4}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2}:{d:0>2} UTC", .{ year, month_day.month, month_day.day, hours, minutes, seconds }); // Sleep for 1 second - std.time.sleep(1 * std.time.ns_per_s); + try std.Io.Clock.Duration.sleep(.{ + .clock = .boot, + .raw = .fromSeconds(1), + }, io); } } diff --git a/src/ziglets/factorial.zig b/src/ziglets/factorial.zig index e91dee5..7a5b48e 100644 --- a/src/ziglets/factorial.zig +++ b/src/ziglets/factorial.zig @@ -9,17 +9,19 @@ const DEFAULT_THREAD_COUNT = 2; /// For n > 34, uses big integer arithmetic to handle arbitrarily large results. /// Usage: ziglets factorial [num_threads] pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void { - const stdout = std.io.getStdOut().writer(); + const io = std.Io.Threaded.global_single_threaded.io(); + var stdout_buffer: [0]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); // Validate command line arguments if (args.len == 0) { - try stdout.print("Usage: ziglets factorial [num_threads]\n", .{}); + try stdout.interface.print("Usage: ziglets factorial [num_threads]\n", .{}); return; } // Parse the input number const n = std.fmt.parseInt(u32, args[0], 10) catch { - try stdout.print("Invalid number: {s}\n", .{args[0]}); + try stdout.interface.print("Invalid number: {s}\n", .{args[0]}); return; }; @@ -31,7 +33,7 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void { // Validate thread count if (num_threads < 1) { - try stdout.print("Number of threads must be at least 1.\n", .{}); + try stdout.interface.print("Number of threads must be at least 1.\n", .{}); return; } @@ -48,26 +50,31 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void { /// Calculates factorial using u128 arithmetic with multithreading for n <= 34 fn calculateU128Factorial(allocator: std.mem.Allocator, n: u32, num_threads: u32) !void { - const stdout = std.io.getStdOut().writer(); - try stdout.print("Calculating {d}! using {d} thread(s) with u128 arithmetic...\n", .{ n, num_threads }); + const io = std.Io.Threaded.global_single_threaded.io(); + var stdout_buffer: [0]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); // Handle special case: 0! = 1 if (n == 0) { - try stdout.print("Result: 1\n", .{}); + try stdout.interface.print("Result: 1\n", .{}); return; } + const effective_num_threads: u32 = if (num_threads == 0) 1 else @min(num_threads, n); + try stdout.interface.print("Calculating {d}! using {d} thread(s) with u128 arithmetic...\n", .{ n, effective_num_threads }); + // Allocate memory for thread handles and partial results - var handles = try allocator.alloc(std.Thread, num_threads); - var results = try allocator.alloc(u128, num_threads); + var handles = try allocator.alloc(std.Thread, effective_num_threads); + var results = try allocator.alloc(u128, effective_num_threads); defer allocator.free(handles); defer allocator.free(results); // Distribute work across threads - const work_distribution = calculateWorkDistribution(n, num_threads); + const work_distribution = try calculateWorkDistribution(allocator, n, effective_num_threads); + defer work_distribution.deinit(allocator); // Spawn threads to compute partial products - for (0..num_threads) |i| { + for (0..effective_num_threads) |i| { const range = work_distribution.ranges[i]; handles[i] = try std.Thread.spawn(std.Thread.SpawnConfig{}, computePartialProduct, .{ range.start, range.end, &results[i] }); } @@ -83,7 +90,7 @@ fn calculateU128Factorial(allocator: std.mem.Allocator, n: u32, num_threads: u32 final_result *= partial_result; } - try stdout.print("Result: {d}\n", .{final_result}); + try stdout.interface.print("Result: {d}\n", .{final_result}); } /// Represents a range of numbers for computation @@ -104,20 +111,19 @@ const WorkDistribution = struct { }; /// Calculates how to distribute work across threads efficiently -fn calculateWorkDistribution(n: u32, num_threads: u32) WorkDistribution { - // This is a simplified version - in practice you'd want to allocate this properly - // For now, we'll use a static array approach for clarity - var ranges: [8]ComputationRange = undefined; // Assume max 8 threads for simplicity +fn calculateWorkDistribution(allocator: std.mem.Allocator, n: u32, num_threads: u32) !WorkDistribution { + const effective_num_threads: u32 = if (num_threads == 0) 1 else @min(num_threads, n); + const ranges = try allocator.alloc(ComputationRange, effective_num_threads); - const chunk_size = n / num_threads; - const remainder = n % num_threads; + const chunk_size = n / effective_num_threads; + const remainder = n % effective_num_threads; var current: u32 = 1; - for (0..num_threads) |i| { + for (0..effective_num_threads) |i| { const start = current; var end: u32 = undefined; - if (i == num_threads - 1) { + if (i == effective_num_threads - 1) { // Last thread takes all remaining numbers end = n; } else { @@ -132,7 +138,7 @@ fn calculateWorkDistribution(n: u32, num_threads: u32) WorkDistribution { current = end + 1; } - return WorkDistribution{ .ranges = ranges[0..num_threads] }; + return WorkDistribution{ .ranges = ranges }; } /// Thread worker function: computes the product of numbers in range [start, end] @@ -154,8 +160,10 @@ fn computePartialProduct(start: u32, end: u32, result: *u128) void { /// Calculates factorial using big integer arithmetic for numbers > 34 /// Uses sequential computation for simplicity and memory efficiency fn calculateBigFactorial(allocator: std.mem.Allocator, n: u32, num_threads: u32) !void { - const stdout = std.io.getStdOut().writer(); - try stdout.print("Calculating {d}! using big integer arithmetic...\n", .{n}); + const io = std.Io.Threaded.global_single_threaded.io(); + var stdout_buffer: [0]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); + try stdout.interface.print("Calculating {d}! using big integer arithmetic...\n", .{n}); // Note: Threading with big integers is complex due to memory management // For now, we use sequential computation which is still very efficient @@ -172,7 +180,7 @@ fn calculateBigFactorial(allocator: std.mem.Allocator, n: u32, num_threads: u32) if (n == 0) { const result_str = try result.toString(allocator, 10, .lower); defer allocator.free(result_str); - try stdout.print("Result: {s}\n", .{result_str}); + try stdout.interface.print("Result: {s}\n", .{result_str}); return; } @@ -193,5 +201,5 @@ fn calculateBigFactorial(allocator: std.mem.Allocator, n: u32, num_threads: u32) const result_str = try result.toString(allocator, 10, .lower); defer allocator.free(result_str); - try stdout.print("Result: {s}\n", .{result_str}); + try stdout.interface.print("Result: {s}\n", .{result_str}); } diff --git a/src/ziglets/guess.zig b/src/ziglets/guess.zig index 8c2fd76..2ff6f31 100644 --- a/src/ziglets/guess.zig +++ b/src/ziglets/guess.zig @@ -1,25 +1,31 @@ const std = @import("std"); pub fn run() !void { - const stdout = std.io.getStdOut().writer(); - const stdin = std.io.getStdIn().reader(); - const secret = std.crypto.random.intRangeAtMost(u32, 1, 100); - try stdout.print("Guess the number (1-100):\n", .{}); + const io = std.Io.Threaded.global_single_threaded.io(); + var stdout_buffer: [0]u8 = undefined; + var stdin_buffer: [128]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); + var stdin = std.Io.File.stdin().reader(io, &stdin_buffer); + var seed: u64 = undefined; + io.random(std.mem.asBytes(&seed)); + var prng = std.Random.DefaultPrng.init(seed); + const secret = prng.random().intRangeAtMost(u32, 1, 100); + try stdout.interface.print("Guess the number (1-100):\n", .{}); while (true) { - try stdout.print("> ", .{}); - var buf: [16]u8 = undefined; - const line = try stdin.readUntilDelimiterOrEof(&buf, '\n'); + try stdout.interface.print("> ", .{}); + const line = try stdin.interface.takeDelimiter('\n'); if (line == null) break; - const guess = std.fmt.parseInt(u32, line.?, 10) catch { - try stdout.print("Please enter a valid number.\n", .{}); + const trimmed = std.mem.trim(u8, line.?, "\r"); + const guess = std.fmt.parseInt(u32, trimmed, 10) catch { + try stdout.interface.print("Please enter a valid number.\n", .{}); continue; }; if (guess < secret) { - try stdout.print("Too low!\n", .{}); + try stdout.interface.print("Too low!\n", .{}); } else if (guess > secret) { - try stdout.print("Too high!\n", .{}); + try stdout.interface.print("Too high!\n", .{}); } else { - try stdout.print("Nice! The number was {d}.\n", .{secret}); + try stdout.interface.print("Nice! The number was {d}.\n", .{secret}); break; } } diff --git a/src/ziglets/pgen.zig b/src/ziglets/pgen.zig index dfd3099..9131aca 100644 --- a/src/ziglets/pgen.zig +++ b/src/ziglets/pgen.zig @@ -20,7 +20,9 @@ const SYMBOL_CHARS = "!@#$%^&*()-_=+[]{}|;:,.<>?/"; /// Main entry point for the password generator tool /// Takes an allocator for memory management and command-line arguments pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void { - const stdout = std.io.getStdOut().writer(); + const io = std.Io.Threaded.global_single_threaded.io(); + var stdout_buffer: [0]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); // Default settings for the password var password_length: usize = 12; // Default length var use_lowercase = false; // Include lowercase letters? @@ -46,7 +48,7 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void { // Check if there's another argument after this one to parse as the length if (i + 1 < args.len) { i += 1; // Move to the next argument - password_length = try parseLength(args[i], stdout); + password_length = try parseLength(args[i], &stdout.interface); } } // Parse character set flags (can be combined, e.g., -aA1&) @@ -73,21 +75,21 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void { // Display help message if requested or if no character set was selected if (show_help or (!use_lowercase and !use_uppercase and !use_numbers and !use_symbols)) { - printHelp(stdout); + printHelp(&stdout.interface); return; } // Generate and display the password - const password = try generatePassword(allocator, stdout, password_length, use_lowercase, use_uppercase, use_numbers, use_symbols); + const password = try generatePassword(allocator, &stdout.interface, password_length, use_lowercase, use_uppercase, use_numbers, use_symbols); defer allocator.free(password); // Output the generated password - try stdout.print("Generated password: {s}\n", .{password}); + try stdout.interface.print("Generated password: {s}\n", .{password}); } /// Parse a string into an unsigned integer for the password length /// Handles errors and enforces minimum and maximum length constraints -fn parseLength(length_str: []const u8, writer: anytype) !usize { +fn parseLength(length_str: []const u8, writer: *std.Io.Writer) !usize { // Parse the string to an integer const length = std.fmt.parseInt(usize, length_str, 10) catch { try writer.print("Error: Invalid length value '{s}'. Using default length of 12.\n", .{length_str}); @@ -109,7 +111,7 @@ fn parseLength(length_str: []const u8, writer: anytype) !usize { } /// Print help information showing how to use the password generator -fn printHelp(writer: anytype) void { +fn printHelp(writer: *std.Io.Writer) void { writer.print( \\Password Generator Usage: \\ ziglets pgen [options] @@ -134,36 +136,42 @@ fn printHelp(writer: anytype) void { /// Generate a random password based on the specified criteria /// This is the core function that builds and returns the password -fn generatePassword(allocator: std.mem.Allocator, writer: anytype, length: usize, use_lowercase: bool, use_uppercase: bool, use_numbers: bool, use_symbols: bool) ![]const u8 { +fn generatePassword(allocator: std.mem.Allocator, writer: *std.Io.Writer, length: usize, use_lowercase: bool, use_uppercase: bool, use_numbers: bool, use_symbols: bool) ![]const u8 { // Create a character pool based on the selected options - var char_pool = std.ArrayList(u8).init(allocator); - defer char_pool.deinit(); + var char_pool = std.ArrayList(u8).empty; + defer char_pool.deinit(allocator); // Add the selected character sets to our pool if (use_lowercase) { - try addCharsToPool(&char_pool, LOWERCASE_CHARS); + try addCharsToPool(allocator, &char_pool, LOWERCASE_CHARS); } if (use_uppercase) { - try addCharsToPool(&char_pool, UPPERCASE_CHARS); + try addCharsToPool(allocator, &char_pool, UPPERCASE_CHARS); } if (use_numbers) { - try addCharsToPool(&char_pool, NUMBER_CHARS); + try addCharsToPool(allocator, &char_pool, NUMBER_CHARS); } if (use_symbols) { - try addCharsToPool(&char_pool, SYMBOL_CHARS); + try addCharsToPool(allocator, &char_pool, SYMBOL_CHARS); } // Ensure we have at least some characters in the pool if (char_pool.items.len == 0) { try writer.print("Warning: No character sets selected. Using lowercase as default.\n", .{}); - try addCharsToPool(&char_pool, LOWERCASE_CHARS); + try addCharsToPool(allocator, &char_pool, LOWERCASE_CHARS); } // Allocate space for the password const password = try allocator.alloc(u8, length); + const io = std.Io.Threaded.global_single_threaded.io(); + var seed: u64 = undefined; + io.random(std.mem.asBytes(&seed)); + var prng = std.Random.DefaultPrng.init(seed); + const random = prng.random(); + // Generate a random password using the crypto module's secure random generator for (0..length) |i| { // Get a random index within the range of the character pool - const random_index = std.crypto.random.uintLessThan(usize, char_pool.items.len); + const random_index = random.uintLessThan(usize, char_pool.items.len); // Use that random index to select a character from our pool password[i] = char_pool.items[random_index]; } @@ -172,8 +180,8 @@ fn generatePassword(allocator: std.mem.Allocator, writer: anytype, length: usize } /// Helper function to add a set of characters to the character pool -fn addCharsToPool(pool: *std.ArrayList(u8), chars: []const u8) !void { +fn addCharsToPool(allocator: std.mem.Allocator, pool: *std.ArrayList(u8), chars: []const u8) !void { for (chars) |char| { - try pool.append(char); + try pool.append(allocator, char); } } diff --git a/src/ziglets/touch.zig b/src/ziglets/touch.zig index 2fb3815..efebb9b 100644 --- a/src/ziglets/touch.zig +++ b/src/ziglets/touch.zig @@ -4,23 +4,26 @@ const std = @import("std"); /// allocator: memory allocator for allocations /// args: command-line arguments (should contain at least one filename) pub fn run(_: std.mem.Allocator, args: []const []const u8) !void { - const stdout = std.io.getStdOut().writer(); // Get the standard output writer + const io = std.Io.Threaded.global_single_threaded.io(); + const cwd = std.Io.Dir.cwd(); + var stdout_buffer: [0]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); // Get the standard output writer // If no filename is provided, print usage and return if (args.len == 0) { - try stdout.print("Usage: ziglets touch [more files...]\n", .{}); + try stdout.interface.print("Usage: ziglets touch [more files...]\n", .{}); return; } // For each filename provided as argument for (args) |filename| { // Try to create the file (write mode, create if not exists, truncate if exists) - var file = std.fs.cwd().createFile(filename, .{ .truncate = true }) catch |err| { + var file = cwd.createFile(io, filename, .{ .truncate = true }) catch |err| { // If there is an error, print a message and continue with the next file - try stdout.print("Could not create file '{s}': {s}\n", .{ filename, @errorName(err) }); + try stdout.interface.print("Could not create file '{s}': {s}\n", .{ filename, @errorName(err) }); continue; }; // Close the file immediately (we just want to create/truncate it) - file.close(); + file.close(io); } } diff --git a/src/ziglets/writer.zig b/src/ziglets/writer.zig index 1609d46..261dc91 100644 --- a/src/ziglets/writer.zig +++ b/src/ziglets/writer.zig @@ -1,6 +1,8 @@ const std = @import("std"); // Import the Zig standard library pub fn run(allocator: std.mem.Allocator, args: []const []const u8) anyerror!void { // Define the 'run' function, takes an allocator and an array of string slices, returns void or error + const io = std.Io.Threaded.global_single_threaded.io(); + const cwd = std.Io.Dir.cwd(); if (args.len < 1) { // If there are no arguments std.debug.print("Usage: ziglets writer \n", .{}); // Print usage instructions return error.InvalidArguments; // Return an error for invalid arguments @@ -11,17 +13,25 @@ pub fn run(allocator: std.mem.Allocator, args: []const []const u8) anyerror!void // Write to file.txt const file_path = "file.txt"; // Set the file path to "file.txt" { - var file = try std.fs.cwd().createFile(file_path, .{ .truncate = true, .read = true }); // Create or truncate "file.txt" for writing and reading - defer file.close(); // Ensure the file is closed when the block ends - try file.writer().writeAll(text); // Write the combined text to the file + var file = try cwd.createFile(io, file_path, .{ .truncate = true, .read = true }); // Create or truncate "file.txt" for writing and reading + defer file.close(io); // Ensure the file is closed when the block ends + var file_buffer: [256]u8 = undefined; + var file_writer = file.writer(io, &file_buffer); + try file_writer.interface.writeAll(text); // Write the combined text to the file + try file_writer.interface.flush(); } // Read and display the content { - var file = try std.fs.cwd().openFile(file_path, .{}); // Open "file.txt" for reading - defer file.close(); // Ensure the file is closed when the block ends + var file = try cwd.openFile(io, file_path, .{}); // Open "file.txt" for reading + defer file.close(io); // Ensure the file is closed when the block ends var buf = try allocator.alloc(u8, 1024); // Allocate a buffer of 1024 bytes - const n = try file.reader().readAll(buf); // Read the file content into the buffer, get the number of bytes read - try std.io.getStdOut().writer().print("file.txt content: {s}\n", .{buf[0..n]}); // Print the content of the file to standard output + defer allocator.free(buf); + var file_buffer: [256]u8 = undefined; + var file_reader = file.reader(io, &file_buffer); + const n = try file_reader.interface.readSliceShort(buf); // Read the file content into the buffer, get the number of bytes read + var stdout_buffer: [0]u8 = undefined; + var stdout = std.Io.File.stdout().writer(io, &stdout_buffer); + try stdout.interface.print("file.txt content: {s}\n", .{buf[0..n]}); // Print the content of the file to standard output } }