| ... | @@ -752,4 +752,40 @@ pub const AnyReader = struct { | ... | @@ -752,4 +752,40 @@ pub const AnyReader = struct { |
| 752 | } | 752 | } |
| 753 | return index; | 753 | return index; |
| 754 | } | 754 | } |
| | 755 | |
| | 756 | pub fn readAllAlloc(self: AnyReader, allocator: std.mem.Allocator, max_size: usize) ![]u8 { |
| | 757 | var array_list = std.ArrayList(u8).init(allocator); |
| | 758 | defer array_list.deinit(); |
| | 759 | try self.readAllArrayList(&array_list, max_size); |
| | 760 | return try array_list.toOwnedSlice(); |
| | 761 | } |
| | 762 | |
| | 763 | pub fn readAllArrayList(self: AnyReader, array_list: *std.ArrayList(u8), max_append_size: usize) !void { |
| | 764 | return self.readAllArrayListAligned(null, array_list, max_append_size); |
| | 765 | } |
| | 766 | |
| | 767 | pub fn readAllArrayListAligned(self: AnyReader, comptime alignment: ?u29, array_list: *std.ArrayListAligned(u8, alignment), max_append_size: usize) !void { |
| | 768 | try array_list.ensureTotalCapacity(@min(max_append_size, 4096)); |
| | 769 | const original_len = array_list.items.len; |
| | 770 | var start_index: usize = original_len; |
| | 771 | while (true) { |
| | 772 | array_list.expandToCapacity(); |
| | 773 | const dest_slice = array_list.items[start_index..]; |
| | 774 | const bytes_read = try self.readAll(dest_slice); |
| | 775 | start_index += bytes_read; |
| | 776 | |
| | 777 | if (start_index - original_len > max_append_size) { |
| | 778 | array_list.shrinkAndFree(original_len + max_append_size); |
| | 779 | return error.StreamTooLong; |
| | 780 | } |
| | 781 | |
| | 782 | if (bytes_read != dest_slice.len) { |
| | 783 | array_list.shrinkAndFree(start_index); |
| | 784 | return; |
| | 785 | } |
| | 786 | |
| | 787 | // This will trigger ArrayList to expand superlinearly at whatever its growth rate is. |
| | 788 | try array_list.ensureTotalCapacity(start_index + 1); |
| | 789 | } |
| | 790 | } |
| 755 | }; | 791 | }; |