| ... | ... | @@ -258,18 +258,6 @@ pub const ArgIteratorWasi = struct { |
| 258 | 258 | } |
| 259 | 259 | }; |
| 260 | 260 | |
| 261 | | test "process.ArgIteratorWasi" { |
| 262 | | if (builtin.os.tag != .wasi) return error.SkipZigTest; |
| 263 | | |
| 264 | | var ga = std.testing.allocator; |
| 265 | | var args_it = try ArgIteratorWasi.init(ga); |
| 266 | | defer args_it.deinit(); |
| 267 | | |
| 268 | | testing.expectEqual(@as(usize, 1), args_it.args.len); |
| 269 | | const prog_name = args_it.next() orelse unreachable; |
| 270 | | testing.expect(mem.eql(u8, "test.wasm", prog_name)); |
| 271 | | } |
| 272 | | |
| 273 | 261 | pub const ArgIteratorWindows = struct { |
| 274 | 262 | index: usize, |
| 275 | 263 | cmd_line: [*]const u8, |
| ... | ... | @@ -429,15 +417,9 @@ pub const ArgIterator = struct { |
| 429 | 417 | inner: InnerType, |
| 430 | 418 | |
| 431 | 419 | /// Initialize the args iterator. |
| 432 | | /// |
| 433 | | /// On WASI, will panic if the default Wasm page allocator runs out of memory |
| 434 | | /// or there is an error fetching the args from the runtime. If you want to |
| 435 | | /// use custom allocator and handle the errors yourself, call `initWasi()` instead. |
| 436 | | /// You also must remember to free the buffer with `deinitWasi()` call. |
| 437 | 420 | pub fn init() ArgIterator { |
| 438 | 421 | if (builtin.os.tag == .wasi) { |
| 439 | | const allocator = std.heap.page_allocator; |
| 440 | | return ArgIterator.initWasi(allocator) catch @panic("unexpected error occurred when initializing ArgIterator"); |
| 422 | @compileError("In WASI, use initWithAllocator instead."); |
| 441 | 423 | } |
| 442 | 424 | |
| 443 | 425 | return ArgIterator{ .inner = InnerType.init() }; |
| ... | ... | @@ -445,10 +427,13 @@ pub const ArgIterator = struct { |
| 445 | 427 | |
| 446 | 428 | pub const InitError = ArgIteratorWasi.InitError; |
| 447 | 429 | |
| 448 | | /// If you are targeting WASI, you can call this to manually specify the allocator and |
| 449 | | /// handle any errors. |
| 450 | | pub fn initWasi(allocator: *mem.Allocator) InitError!ArgIterator { |
| 451 | | return ArgIterator{ .inner = try InnerType.init(allocator) }; |
| 430 | /// You must deinitialize iterator's internal buffers by calling `deinit` when done. |
| 431 | pub fn initWithAllocator(allocator: *mem.Allocator) InitError!ArgIterator { |
| 432 | if (builtin.os.tag == .wasi) { |
| 433 | return ArgIterator{ .inner = try InnerType.init(allocator) }; |
| 434 | } |
| 435 | |
| 436 | return ArgIterator{ .inner = InnerType.init() }; |
| 452 | 437 | } |
| 453 | 438 | |
| 454 | 439 | pub const NextError = ArgIteratorWindows.NextError; |
| ... | ... | @@ -478,10 +463,13 @@ pub const ArgIterator = struct { |
| 478 | 463 | return self.inner.skip(); |
| 479 | 464 | } |
| 480 | 465 | |
| 481 | | /// If you are targeting WASI, call this to free the iterator's internal buffer |
| 482 | | /// after you are done with it. |
| 483 | | pub fn deinitWasi(self: *ArgIterator) void { |
| 484 | | self.inner.deinit(); |
| 466 | /// Call this to free the iterator's internal buffer if the iterator |
| 467 | /// was created with `initWithAllocator` function. |
| 468 | pub fn deinit(self: *ArgIterator) void { |
| 469 | // Unless we're targeting WASI, this is a no-op. |
| 470 | if (builtin.os.tag == .wasi) { |
| 471 | self.inner.deinit(); |
| 472 | } |
| 485 | 473 | } |
| 486 | 474 | }; |
| 487 | 475 | |
| ... | ... | @@ -489,11 +477,33 @@ pub fn args() ArgIterator { |
| 489 | 477 | return ArgIterator.init(); |
| 490 | 478 | } |
| 491 | 479 | |
| 480 | /// You must deinitialize iterator's internal buffers by calling `deinit` when done. |
| 481 | pub fn argsWithAllocator(allocator: *mem.Allocator) ArgIterator.InitError!ArgIterator { |
| 482 | return ArgIterator.initWithAllocator(allocator); |
| 483 | } |
| 484 | |
| 485 | test "args iterator" { |
| 486 | var ga = std.testing.allocator; |
| 487 | var it = if (builtin.os.tag == .wasi) argsWithAllocator(ga) else args(); |
| 488 | defer it.deinit(); // no-op unless WASI |
| 489 | |
| 490 | testing.expect(it.skip()); |
| 491 | const prog_name = it.next(ga) orelse unreachable; |
| 492 | defer ga.free(prog_name); |
| 493 | |
| 494 | const expected_bin_name = switch (builtin.os.tag) { |
| 495 | .wasi => "test.wasm", |
| 496 | .windows => "test.exe", |
| 497 | else => "test", |
| 498 | }; |
| 499 | testing.expect(mem.eql(u8, expected_bin_name, prog_name)); |
| 500 | } |
| 501 | |
| 492 | 502 | /// Caller must call argsFree on result. |
| 493 | 503 | pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { |
| 494 | 504 | // TODO refactor to only make 1 allocation. |
| 495 | | var it = args(); |
| 496 | | defer if (builtin.os.tag == .wasi) it.deinitWasi(); |
| 505 | var it = if (builtin.os.tag == .wasi) argsWithAllocator(allocator) else args(); |
| 506 | defer it.deinit(); |
| 497 | 507 | |
| 498 | 508 | var contents = std.ArrayList(u8).init(allocator); |
| 499 | 509 | defer contents.deinit(); |