authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-02 19:10:01 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-02 19:10:01 -08:00
log2703e94cdd934a3575f803641f3f59ad7012b37e
tree63faa503a4e6435204210a6465c9ba0563e4c3fa
parent666575baab3f4b935b7ae2db8b2aa8ec44af20a9

add Readable.readAllAlloc()


1 files changed, 42 insertions(+), 0 deletions(-)

nio.zig+42
...@@ -44,6 +44,48 @@ pub fn Readable(T: type, this_kind: enum { _var, _const, _bare }) type {...@@ -44,6 +44,48 @@ pub fn Readable(T: type, this_kind: enum { _var, _const, _bare }) type {
44 const amt_read = try self.readAll(buf);44 const amt_read = try self.readAll(buf);
45 if (amt_read < buf.len) return error.EndOfStream;45 if (amt_read < buf.len) return error.EndOfStream;
46 }46 }
47
48 /// Appends to the `std.ArrayList` contents by reading from the stream until end of stream is found.
49 /// If the number of bytes appended would exceed `max_append_size`, `error.StreamTooLong` is returned and the `std.ArrayList` has exactly `max_append_size` bytes appended.
50 fn readAllArrayList(self: Self, array_list: *std.ArrayList(u8), max_append_size: usize) !void {
51 return self.readAllArrayListAligned(null, array_list, max_append_size);
52 }
53
54 fn readAllArrayListAligned(self: Self, comptime alignment: ?u29, array_list: *std.ArrayListAligned(u8, alignment), max_append_size: usize) !void {
55 try array_list.ensureTotalCapacity(@min(max_append_size, 4096));
56 const original_len = array_list.items.len;
57 var start_index: usize = original_len;
58 while (true) {
59 array_list.expandToCapacity();
60 const dest_slice = array_list.items[start_index..];
61 const bytes_read = try self.readAll(dest_slice);
62 start_index += bytes_read;
63
64 if (start_index - original_len > max_append_size) {
65 array_list.shrinkAndFree(original_len + max_append_size);
66 return error.StreamTooLong;
67 }
68
69 if (bytes_read != dest_slice.len) {
70 array_list.shrinkAndFree(start_index);
71 return;
72 }
73
74 // This will trigger ArrayList to expand superlinearly at whatever its growth rate is.
75 try array_list.ensureTotalCapacity(start_index + 1);
76 }
77 }
78
79 /// Allocates enough memory to hold all the contents of the stream.
80 /// If the allocated memory would be greater than `max_size`, returns `error.StreamTooLong`.
81 /// Caller owns returned memory.
82 /// If this function returns an error, the contents from the stream read so far are lost.
83 pub fn readAllAlloc(self: Self, allocator: std.mem.Allocator, max_size: usize) ![]u8 {
84 var array_list = std.ArrayList(u8).init(allocator);
85 defer array_list.deinit();
86 try self.readAllArrayList(&array_list, max_size);
87 return try array_list.toOwnedSlice();
88 }
47 };89 };
48}90}
4991