authorgravatar for eugenelf10@gmail.comTen Eugene <eugenelf10@gmail.com> 2026-09-21 07:53:28+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-09-21 07:53:28+02:00
log230c63650ff5ab470594a8b44e06be69654113e9
tree7cc4cca200cb7623c77505ca6ef744a020938834
parentabe2216699d46be45b32215733247db0e3a5e620

std.Io.Reader: add readAllocShort, mirror readAlloc* with readSlice* (#36807)

Closes #36767 Reviewed-on: https://codeberg.org/ziglang/zig/pulls/36807 Reviewed-by: Ryan Liptak <squeek502@noreply.codeberg.org>

5 files changed, 65 insertions(+), 11 deletions(-)

lib/compiler/objcopy.zig+1-1
......@@ -409,7 +409,7 @@ const BinaryElfOutput = struct {
409409 const shstrtab_shdr = (try section_headers.next()).?;
410410
411411 try in.seekTo(shstrtab_shdr.sh_offset);
412 break :blk try in.interface.readAlloc(allocator, shstrtab_shdr.sh_size);
412 break :blk try in.interface.readAllocAll(allocator, shstrtab_shdr.sh_size);
413413 };
414414
415415 errdefer if (self.shstrtab) |shstrtab| allocator.free(shstrtab);
lib/compiler/objdump.zig+4-4
......@@ -417,7 +417,7 @@ const coff = struct {
417417 \\
418418 );
419419
420 const offsets = try r.readAlloc(gpa, num_symbols * 4);
420 const offsets = try r.readAllocAll(gpa, num_symbols * 4);
421421 defer gpa.free(offsets);
422422
423423 for (0..num_symbols) |symbol_i| {
......@@ -549,7 +549,7 @@ const coff = struct {
549549 .longnames => {
550550 // This member is optional
551551 if (std.mem.eql(u8, header.name, "//")) {
552 opt_longnames = try r.readAlloc(gpa, header.size);
552 opt_longnames = try r.readAllocAll(gpa, header.size);
553553 if (dump_header)
554554 try w.print("{t: >16} type\n", .{expected_kind});
555555
......@@ -819,7 +819,7 @@ const coff = struct {
819819 const string_table_len = r.peekInt(u32, .little) catch |err|
820820 return d.failParse("unable to read string table length: {t}", .{err});
821821
822 const table = r.readAlloc(gpa, string_table_len) catch |err|
822 const table = r.readAllocAll(gpa, string_table_len) catch |err|
823823 return d.failParse("unable to read string table: {t}", .{err});
824824
825825 try fr.seekTo(pos);
......@@ -1268,7 +1268,7 @@ const coff = struct {
12681268 const dir = image_info.?.data_dirs[@backingInt(DIRECTORY_ENTRY.EXPORT)];
12691269 const dir_end_rva = dir.virtual_address + dir.size;
12701270 const dir_loc = fr.logicalPos();
1271 const dir_slice = try r.readAlloc(gpa, dir.size);
1271 const dir_slice = try r.readAllocAll(gpa, dir.size);
12721272 defer gpa.free(dir_slice);
12731273
12741274 const dll_name = std.mem.sliceTo(dir_slice[name_loc - dir_loc ..], 0);
lib/std/Io/Reader.zig+55-1
......@@ -744,14 +744,27 @@ pub inline fn readSliceEndianAlloc(
744744 return dest;
745745}
746746
747/// Deprecated; use readAllocAll. to be removed after 0.17.
748pub const readAlloc = readAllocAll;
749
747750/// Shortcut for calling `readSliceAll` with a buffer provided by `allocator`.
748pub fn readAlloc(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 {
751pub fn readAllocAll(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 {
749752 const dest = try allocator.alloc(u8, len);
750753 errdefer allocator.free(dest);
751754 try readSliceAll(r, dest);
752755 return dest;
753756}
754757
758/// Shortcut for calling `readSliceShort` with a buffer provided by `allocator`,
759/// shrinking allocation if stream reached the end.
760pub fn readAllocShort(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 {
761 const dest = try allocator.alloc(u8, len);
762 errdefer allocator.free(dest);
763 const n = try readSliceShort(r, dest);
764 if (n == dest.len) return dest;
765 return try allocator.realloc(dest, n);
766}
767
755768pub const DelimiterError = error{
756769 /// See the `Reader` implementation for detailed diagnostics.
757770 ReadFailed,
......@@ -1746,6 +1759,47 @@ test "readSliceShort with indirect reader" {
17461759 try testing.expectEqual(0, try ri.interface.readSliceShort(&buf));
17471760}
17481761
1762test readAllocAll {
1763 const allocator = testing.allocator;
1764 var r: Reader = .fixed("HelloFren");
1765
1766 const s1 = try r.readAllocAll(allocator, 5);
1767 defer allocator.free(s1);
1768 try testing.expectEqualStrings("Hello", s1);
1769
1770 const s2 = try r.readAllocAll(allocator, 4);
1771 defer allocator.free(s2);
1772 try testing.expectEqualStrings("Fren", s2);
1773}
1774
1775test "readAllocAll with buffer bigger than content" {
1776 const allocator = testing.allocator;
1777 var r: Reader = .fixed("HelloFren");
1778
1779 const s1 = try r.readAllocAll(allocator, 5);
1780 defer allocator.free(s1);
1781 try testing.expectEqualStrings("Hello", s1);
1782
1783 const res = r.readAllocAll(allocator, 10);
1784 try testing.expectError(Error.EndOfStream, res);
1785}
1786
1787test readAllocShort {
1788 var r: Reader = .fixed("HelloFren");
1789
1790 const s1 = try r.readAllocShort(testing.allocator, 5);
1791 defer testing.allocator.free(s1);
1792 try testing.expectEqualStrings("Hello", s1);
1793
1794 const s2 = try r.readAllocShort(testing.allocator, 10);
1795 defer testing.allocator.free(s2);
1796 try testing.expectEqualStrings("Fren", s2);
1797
1798 const s3 = try r.readAllocShort(testing.allocator, 10);
1799 defer testing.allocator.free(s3);
1800 try testing.expectEqual(0, s3.len);
1801}
1802
17491803test readVec {
17501804 var r: Reader = .fixed(std.ascii.letters);
17511805 var flat_buffer: [52]u8 = undefined;
lib/std/debug/Pdb.zig+4-4
......@@ -171,7 +171,7 @@ pub fn parseIpiStream(self: *Pdb) !void {
171171 const header = try stream.interface.peekStruct(pdb.IpiStreamHeader, .little);
172172 if (header.version != .v80) // only value observed by LLVM team
173173 return error.UnknownPDBVersion;
174 self.ipi = try stream.interface.readAlloc(gpa, @sizeOf(pdb.IpiStreamHeader) + header.type_record_bytes);
174 self.ipi = try stream.interface.readAllocAll(gpa, @sizeOf(pdb.IpiStreamHeader) + header.type_record_bytes);
175175}
176176
177177pub fn parseInfoStream(self: *Pdb) !void {
......@@ -196,7 +196,7 @@ pub fn parseInfoStream(self: *Pdb) !void {
196196 // Find the string table.
197197 const string_table_index = str_tab_index: {
198198 const name_bytes_len = try reader.takeInt(u32, .little);
199 const name_bytes = try reader.readAlloc(gpa, name_bytes_len);
199 const name_bytes = try reader.readAllocAll(gpa, name_bytes_len);
200200 defer gpa.free(name_bytes);
201201
202202 const HashTableHeader = extern struct {
......@@ -865,9 +865,9 @@ pub fn getModule(self: *Pdb, index: usize) !?*Module {
865865
866866 const gpa = self.allocator;
867867
868 mod.symbols = try reader.readAlloc(gpa, mod.mod_info.sym_byte_size - 4);
868 mod.symbols = try reader.readAllocAll(gpa, mod.mod_info.sym_byte_size - 4);
869869 errdefer gpa.free(mod.symbols);
870 mod.subsect_info = try reader.readAlloc(gpa, mod.mod_info.c13_byte_size);
870 mod.subsect_info = try reader.readAllocAll(gpa, mod.mod_info.c13_byte_size);
871871 errdefer gpa.free(mod.subsect_info);
872872 mod.inlinee_source_lines = b: {
873873 var inlinee_source_lines: std.ArrayList(*align(1) const pdb.InlineeSourceLine) = .empty;
src/link/Coff.zig+1-1
......@@ -5290,7 +5290,7 @@ fn loadArchive(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) Loa
52905290 .longnames => {
52915291 // This member is optional
52925292 if (std.mem.eql(u8, res.name, "//"))
5293 opt_longnames = try r.readAlloc(gpa, @intCast(res.size));
5293 opt_longnames = try r.readAllocAll(gpa, @intCast(res.size));
52945294
52955295 opt_expected_kind = null;
52965296 break;