| ... | @@ -1,3 +1,5 @@ | ... | @@ -1,3 +1,5 @@ |
| | 1 | const Io = @This(); |
| | 2 | |
| 1 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 2 | const is_windows = builtin.os.tag == .windows; | 4 | const is_windows = builtin.os.tag == .windows; |
| 3 | | 5 | |
| ... | @@ -9,79 +11,6 @@ const assert = std.debug.assert; | ... | @@ -9,79 +11,6 @@ const assert = std.debug.assert; |
| 9 | const Allocator = std.mem.Allocator; | 11 | const Allocator = std.mem.Allocator; |
| 10 | const Alignment = std.mem.Alignment; | 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 | pub fn poll( | 14 | pub fn poll( |
| 86 | gpa: Allocator, | 15 | gpa: Allocator, |
| 87 | comptime StreamEnum: type, | 16 | comptime StreamEnum: type, |
| ... | @@ -529,16 +458,8 @@ pub fn PollFiles(comptime StreamEnum: type) type { | ... | @@ -529,16 +458,8 @@ pub fn PollFiles(comptime StreamEnum: type) type { |
| 529 | return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(Io.File), &@splat(.{})); | 458 | return @Struct(.auto, null, std.meta.fieldNames(StreamEnum), &@splat(Io.File), &@splat(.{})); |
| 530 | } | 459 | } |
| 531 | | 460 | |
| 532 | test { | 461 | userdata: ?*anyopaque, |
| 533 | _ = net; | 462 | vtable: *const VTable, |
| 534 | _ = Reader; | | |
| 535 | _ = Writer; | | |
| 536 | _ = Evented; | | |
| 537 | _ = Threaded; | | |
| 538 | _ = @import("Io/test.zig"); | | |
| 539 | } | | |
| 540 | | | |
| 541 | const Io = @This(); | | |
| 542 | | 463 | |
| 543 | pub const Threaded = @import("Io/Threaded.zig"); | 464 | pub const Threaded = @import("Io/Threaded.zig"); |
| 544 | pub const Evented = switch (builtin.os.tag) { | 465 | pub const Evented = switch (builtin.os.tag) { |
| ... | @@ -554,10 +475,13 @@ pub const Evented = switch (builtin.os.tag) { | ... | @@ -554,10 +475,13 @@ pub const Evented = switch (builtin.os.tag) { |
| 554 | }; | 475 | }; |
| 555 | pub const Kqueue = @import("Io/Kqueue.zig"); | 476 | pub const Kqueue = @import("Io/Kqueue.zig"); |
| 556 | pub const IoUring = @import("Io/IoUring.zig"); | 477 | pub const IoUring = @import("Io/IoUring.zig"); |
| 557 | pub const net = @import("Io/net.zig"); | | |
| 558 | | 478 | |
| 559 | userdata: ?*anyopaque, | 479 | pub const Reader = @import("Io/Reader.zig"); |
| 560 | vtable: *const VTable, | 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 | pub const VTable = struct { | 486 | pub const VTable = struct { |
| 563 | /// If it returns `null` it means `result` has been already populated and | 487 | /// If it returns `null` it means `result` has been already populated and |
| ... | @@ -756,6 +680,76 @@ pub const VTable = struct { | ... | @@ -756,6 +680,76 @@ pub const VTable = struct { |
| 756 | netLookup: *const fn (?*anyopaque, net.HostName, *Queue(net.HostName.LookupResult), net.HostName.LookupOptions) net.HostName.LookupError!void, | 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 | pub const Cancelable = error{ | 753 | pub const Cancelable = error{ |
| 760 | /// Caller has requested the async operation to stop. | 754 | /// Caller has requested the async operation to stop. |
| 761 | Canceled, | 755 | Canceled, |
| ... | @@ -773,10 +767,6 @@ pub const UnexpectedError = error{ | ... | @@ -773,10 +767,6 @@ pub const UnexpectedError = error{ |
| 773 | Unexpected, | 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 | pub const Clock = enum { | 770 | pub const Clock = enum { |
| 781 | /// A settable system-wide clock that measures real (i.e. wall-clock) | 771 | /// A settable system-wide clock that measures real (i.e. wall-clock) |
| 782 | /// time. This clock is affected by discontinuous jumps in the system | 772 | /// time. This clock is affected by discontinuous jumps in the system |
| ... | @@ -2281,3 +2271,14 @@ pub const RandomSecureError = error{EntropyUnavailable} || Cancelable; | ... | @@ -2281,3 +2271,14 @@ pub const RandomSecureError = error{EntropyUnavailable} || Cancelable; |
| 2281 | pub fn randomSecure(io: Io, buffer: []u8) RandomSecureError!void { | 2271 | pub fn randomSecure(io: Io, buffer: []u8) RandomSecureError!void { |
| 2282 | return io.vtable.randomSecure(io.userdata, buffer); | 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 | } |