| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | const Io = @This(); |
| 2 | |
| 1 | 3 | const builtin = @import("builtin"); |
| 2 | 4 | const is_windows = builtin.os.tag == .windows; |
| 3 | 5 | |
| ... | ... | @@ -9,79 +11,6 @@ const assert = std.debug.assert; |
| 9 | 11 | const Allocator = std.mem.Allocator; |
| 10 | 12 | const Alignment = std.mem.Alignment; |
| 11 | 13 | |
| 12 | | pub const Limit = enum(usize) { |
| 13 | | nothing = 0, |
| 14 | | unlimited = std.math.maxInt(usize), |
| 15 | | _, |
| 16 | | |
| 17 | | /// `std.math.maxInt(usize)` is interpreted to mean `.unlimited`. |
| 18 | | pub fn limited(n: usize) Limit { |
| 19 | | return @enumFromInt(n); |
| 20 | | } |
| 21 | | |
| 22 | | /// Any value grater than `std.math.maxInt(usize)` is interpreted to mean |
| 23 | | /// `.unlimited`. |
| 24 | | pub fn limited64(n: u64) Limit { |
| 25 | | return @enumFromInt(@min(n, std.math.maxInt(usize))); |
| 26 | | } |
| 27 | | |
| 28 | | pub fn countVec(data: []const []const u8) Limit { |
| 29 | | var total: usize = 0; |
| 30 | | for (data) |d| total += d.len; |
| 31 | | return .limited(total); |
| 32 | | } |
| 33 | | |
| 34 | | pub fn min(a: Limit, b: Limit) Limit { |
| 35 | | return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b))); |
| 36 | | } |
| 37 | | |
| 38 | | pub fn minInt(l: Limit, n: usize) usize { |
| 39 | | return @min(n, @intFromEnum(l)); |
| 40 | | } |
| 41 | | |
| 42 | | pub fn minInt64(l: Limit, n: u64) usize { |
| 43 | | return @min(n, @intFromEnum(l)); |
| 44 | | } |
| 45 | | |
| 46 | | pub fn slice(l: Limit, s: []u8) []u8 { |
| 47 | | return s[0..l.minInt(s.len)]; |
| 48 | | } |
| 49 | | |
| 50 | | pub fn sliceConst(l: Limit, s: []const u8) []const u8 { |
| 51 | | return s[0..l.minInt(s.len)]; |
| 52 | | } |
| 53 | | |
| 54 | | pub fn toInt(l: Limit) ?usize { |
| 55 | | return switch (l) { |
| 56 | | else => @intFromEnum(l), |
| 57 | | .unlimited => null, |
| 58 | | }; |
| 59 | | } |
| 60 | | |
| 61 | | /// Reduces a slice to account for the limit, leaving room for one extra |
| 62 | | /// byte above the limit, allowing for the use case of differentiating |
| 63 | | /// between end-of-stream and reaching the limit. |
| 64 | | pub fn slice1(l: Limit, non_empty_buffer: []u8) []u8 { |
| 65 | | assert(non_empty_buffer.len >= 1); |
| 66 | | return non_empty_buffer[0..@min(@intFromEnum(l) +| 1, non_empty_buffer.len)]; |
| 67 | | } |
| 68 | | |
| 69 | | pub fn nonzero(l: Limit) bool { |
| 70 | | return @intFromEnum(l) > 0; |
| 71 | | } |
| 72 | | |
| 73 | | /// Return a new limit reduced by `amount` or return `null` indicating |
| 74 | | /// limit would be exceeded. |
| 75 | | pub fn subtract(l: Limit, amount: usize) ?Limit { |
| 76 | | if (l == .unlimited) return .unlimited; |
| 77 | | if (amount > @intFromEnum(l)) return null; |
| 78 | | return @enumFromInt(@intFromEnum(l) - amount); |
| 79 | | } |
| 80 | | }; |
| 81 | | |
| 82 | | pub const Reader = @import("Io/Reader.zig"); |
| 83 | | pub const Writer = @import("Io/Writer.zig"); |
| 84 | | |
| 85 | 14 | pub fn poll( |
| 86 | 15 | gpa: Allocator, |
| 87 | 16 | comptime StreamEnum: type, |
| ... | ... | @@ -529,16 +458,8 @@ pub fn PollFiles(comptime StreamEnum: type) type { |
| 529 | 458 | return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(Io.File), &@splat(.{})); |
| 530 | 459 | } |
| 531 | 460 | |
| 532 | | test { |
| 533 | | _ = net; |
| 534 | | _ = Reader; |
| 535 | | _ = Writer; |
| 536 | | _ = Evented; |
| 537 | | _ = Threaded; |
| 538 | | _ = @import("Io/test.zig"); |
| 539 | | } |
| 540 | | |
| 541 | | const Io = @This(); |
| 461 | userdata: ?*anyopaque, |
| 462 | vtable: *const VTable, |
| 542 | 463 | |
| 543 | 464 | pub const Threaded = @import("Io/Threaded.zig"); |
| 544 | 465 | pub const Evented = switch (builtin.os.tag) { |
| ... | ... | @@ -554,10 +475,13 @@ pub const Evented = switch (builtin.os.tag) { |
| 554 | 475 | }; |
| 555 | 476 | pub const Kqueue = @import("Io/Kqueue.zig"); |
| 556 | 477 | pub const IoUring = @import("Io/IoUring.zig"); |
| 557 | | pub const net = @import("Io/net.zig"); |
| 558 | 478 | |
| 559 | | userdata: ?*anyopaque, |
| 560 | | vtable: *const VTable, |
| 479 | pub const Reader = @import("Io/Reader.zig"); |
| 480 | pub const Writer = @import("Io/Writer.zig"); |
| 481 | pub const net = @import("Io/net.zig"); |
| 482 | pub const Dir = @import("Io/Dir.zig"); |
| 483 | pub const File = @import("Io/File.zig"); |
| 484 | pub const Terminal = @import("Io/Terminal.zig"); |
| 561 | 485 | |
| 562 | 486 | pub const VTable = struct { |
| 563 | 487 | /// If it returns `null` it means `result` has been already populated and |
| ... | ... | @@ -756,6 +680,76 @@ pub const VTable = struct { |
| 756 | 680 | netLookup: *const fn (?*anyopaque, net.HostName, *Queue(net.HostName.LookupResult), net.HostName.LookupOptions) net.HostName.LookupError!void, |
| 757 | 681 | }; |
| 758 | 682 | |
| 683 | pub const Limit = enum(usize) { |
| 684 | nothing = 0, |
| 685 | unlimited = std.math.maxInt(usize), |
| 686 | _, |
| 687 | |
| 688 | /// `std.math.maxInt(usize)` is interpreted to mean `.unlimited`. |
| 689 | pub fn limited(n: usize) Limit { |
| 690 | return @enumFromInt(n); |
| 691 | } |
| 692 | |
| 693 | /// Any value grater than `std.math.maxInt(usize)` is interpreted to mean |
| 694 | /// `.unlimited`. |
| 695 | pub fn limited64(n: u64) Limit { |
| 696 | return @enumFromInt(@min(n, std.math.maxInt(usize))); |
| 697 | } |
| 698 | |
| 699 | pub fn countVec(data: []const []const u8) Limit { |
| 700 | var total: usize = 0; |
| 701 | for (data) |d| total += d.len; |
| 702 | return .limited(total); |
| 703 | } |
| 704 | |
| 705 | pub fn min(a: Limit, b: Limit) Limit { |
| 706 | return @enumFromInt(@min(@intFromEnum(a), @intFromEnum(b))); |
| 707 | } |
| 708 | |
| 709 | pub fn minInt(l: Limit, n: usize) usize { |
| 710 | return @min(n, @intFromEnum(l)); |
| 711 | } |
| 712 | |
| 713 | pub fn minInt64(l: Limit, n: u64) usize { |
| 714 | return @min(n, @intFromEnum(l)); |
| 715 | } |
| 716 | |
| 717 | pub fn slice(l: Limit, s: []u8) []u8 { |
| 718 | return s[0..l.minInt(s.len)]; |
| 719 | } |
| 720 | |
| 721 | pub fn sliceConst(l: Limit, s: []const u8) []const u8 { |
| 722 | return s[0..l.minInt(s.len)]; |
| 723 | } |
| 724 | |
| 725 | pub fn toInt(l: Limit) ?usize { |
| 726 | return switch (l) { |
| 727 | else => @intFromEnum(l), |
| 728 | .unlimited => null, |
| 729 | }; |
| 730 | } |
| 731 | |
| 732 | /// Reduces a slice to account for the limit, leaving room for one extra |
| 733 | /// byte above the limit, allowing for the use case of differentiating |
| 734 | /// between end-of-stream and reaching the limit. |
| 735 | pub fn slice1(l: Limit, non_empty_buffer: []u8) []u8 { |
| 736 | assert(non_empty_buffer.len >= 1); |
| 737 | return non_empty_buffer[0..@min(@intFromEnum(l) +| 1, non_empty_buffer.len)]; |
| 738 | } |
| 739 | |
| 740 | pub fn nonzero(l: Limit) bool { |
| 741 | return @intFromEnum(l) > 0; |
| 742 | } |
| 743 | |
| 744 | /// Return a new limit reduced by `amount` or return `null` indicating |
| 745 | /// limit would be exceeded. |
| 746 | pub fn subtract(l: Limit, amount: usize) ?Limit { |
| 747 | if (l == .unlimited) return .unlimited; |
| 748 | if (amount > @intFromEnum(l)) return null; |
| 749 | return @enumFromInt(@intFromEnum(l) - amount); |
| 750 | } |
| 751 | }; |
| 752 | |
| 759 | 753 | pub const Cancelable = error{ |
| 760 | 754 | /// Caller has requested the async operation to stop. |
| 761 | 755 | Canceled, |
| ... | ... | @@ -773,10 +767,6 @@ pub const UnexpectedError = error{ |
| 773 | 767 | Unexpected, |
| 774 | 768 | }; |
| 775 | 769 | |
| 776 | | pub const Dir = @import("Io/Dir.zig"); |
| 777 | | pub const File = @import("Io/File.zig"); |
| 778 | | pub const Terminal = @import("Io/Terminal.zig"); |
| 779 | | |
| 780 | 770 | pub const Clock = enum { |
| 781 | 771 | /// A settable system-wide clock that measures real (i.e. wall-clock) |
| 782 | 772 | /// time. This clock is affected by discontinuous jumps in the system |
| ... | ... | @@ -2281,3 +2271,14 @@ pub const RandomSecureError = error{EntropyUnavailable} || Cancelable; |
| 2281 | 2271 | pub fn randomSecure(io: Io, buffer: []u8) RandomSecureError!void { |
| 2282 | 2272 | return io.vtable.randomSecure(io.userdata, buffer); |
| 2283 | 2273 | } |
| 2274 | |
| 2275 | test { |
| 2276 | _ = net; |
| 2277 | _ = File; |
| 2278 | _ = Dir; |
| 2279 | _ = Reader; |
| 2280 | _ = Writer; |
| 2281 | _ = Evented; |
| 2282 | _ = Threaded; |
| 2283 | _ = @import("Io/test.zig"); |
| 2284 | } |