From a259379b46efa1c8741de50b45933652a261775c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 27 Aug 2025 19:51:12 -0700 Subject: [PATCH] std.Io: delete CountingReader --- lib/std/Build/Step/CheckObject.zig | 58 +++++++++--------------------- lib/std/Io.zig | 5 --- lib/std/Io/counting_reader.zig | 43 ---------------------- src/arch/x86_64/Disassembler.zig | 42 ++++++++++++---------- src/link/MachO/Dwarf.zig | 30 ++++++++-------- src/link/MachO/Dylib.zig | 40 +++++---------------- src/link/MachO/eh_frame.zig | 33 ++++++++--------- 7 files changed, 77 insertions(+), 174 deletions(-) delete mode 100644 lib/std/Io/counting_reader.zig diff --git a/lib/std/Build/Step/CheckObject.zig b/lib/std/Build/Step/CheckObject.zig index 1e321de50a1e..06e74376b0e6 100644 --- a/lib/std/Build/Step/CheckObject.zig +++ b/lib/std/Build/Step/CheckObject.zig @@ -1224,14 +1224,12 @@ const MachODumper = struct { } fn parseRebaseInfo(ctx: ObjectContext, data: []const u8, rebases: *std.array_list.Managed(u64)) !void { - var stream = std.io.fixedBufferStream(data); - var creader = std.io.countingReader(stream.reader()); - const reader = creader.reader(); + var reader: std.Io.Reader = .fixed(data); var seg_id: ?u8 = null; var offset: u64 = 0; while (true) { - const byte = reader.readByte() catch break; + const byte = reader.takeByte() catch break; const opc = byte & macho.REBASE_OPCODE_MASK; const imm = byte & macho.REBASE_IMMEDIATE_MASK; switch (opc) { @@ -1239,17 +1237,17 @@ const MachODumper = struct { macho.REBASE_OPCODE_SET_TYPE_IMM => {}, macho.REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => { seg_id = imm; - offset = try std.leb.readUleb128(u64, reader); + offset = try reader.takeLeb128(u64); }, macho.REBASE_OPCODE_ADD_ADDR_IMM_SCALED => { offset += imm * @sizeOf(u64); }, macho.REBASE_OPCODE_ADD_ADDR_ULEB => { - const addend = try std.leb.readUleb128(u64, reader); + const addend = try reader.takeLeb128(u64); offset += addend; }, macho.REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB => { - const addend = try std.leb.readUleb128(u64, reader); + const addend = try reader.takeLeb128(u64); const seg = ctx.segments.items[seg_id.?]; const addr = seg.vmaddr + offset; try rebases.append(addr); @@ -1266,11 +1264,11 @@ const MachODumper = struct { ntimes = imm; }, macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES => { - ntimes = try std.leb.readUleb128(u64, reader); + ntimes = try reader.takeLeb128(u64); }, macho.REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB => { - ntimes = try std.leb.readUleb128(u64, reader); - skip = try std.leb.readUleb128(u64, reader); + ntimes = try reader.takeLeb128(u64); + skip = try reader.takeLeb128(u64); }, else => unreachable, } @@ -1431,7 +1429,7 @@ const MachODumper = struct { defer arena.deinit(); var exports = std.array_list.Managed(Export).init(arena.allocator()); - var it = TrieIterator{ .data = data }; + var it: TrieIterator = .{ .stream = .fixed(data) }; try parseTrieNode(arena.allocator(), &it, "", &exports); mem.sort(Export, exports.items, {}, Export.lessThan); @@ -1462,42 +1460,18 @@ const MachODumper = struct { } const TrieIterator = struct { - data: []const u8, - pos: usize = 0, - - fn getStream(it: *TrieIterator) std.io.FixedBufferStream([]const u8) { - return std.io.fixedBufferStream(it.data[it.pos..]); - } + stream: std.Io.Reader, fn readUleb128(it: *TrieIterator) !u64 { - var stream = it.getStream(); - var creader = std.io.countingReader(stream.reader()); - const reader = creader.reader(); - const value = try std.leb.readUleb128(u64, reader); - it.pos += creader.bytes_read; - return value; + return it.stream.takeLeb128(u64); } fn readString(it: *TrieIterator) ![:0]const u8 { - var stream = it.getStream(); - const reader = stream.reader(); - - var count: usize = 0; - while (true) : (count += 1) { - const byte = try reader.readByte(); - if (byte == 0) break; - } - - const str = @as([*:0]const u8, @ptrCast(it.data.ptr + it.pos))[0..count :0]; - it.pos += count + 1; - return str; + return it.stream.takeSentinel(0); } fn readByte(it: *TrieIterator) !u8 { - var stream = it.getStream(); - const value = try stream.reader().readByte(); - it.pos += 1; - return value; + return it.stream.takeByte(); } }; @@ -1594,10 +1568,10 @@ const MachODumper = struct { const label = try it.readString(); const off = try it.readUleb128(); const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label }); - const curr = it.pos; - it.pos = off; + const curr = it.stream.seek; + it.stream.seek = off; try parseTrieNode(arena, it, prefix_label, exports); - it.pos = curr; + it.stream.seek = curr; } } diff --git a/lib/std/Io.zig b/lib/std/Io.zig index 9c91e1159dc4..9f7a9251ba80 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -277,10 +277,6 @@ pub const AnyReader = @import("Io/DeprecatedReader.zig"); pub const FixedBufferStream = @import("Io/fixed_buffer_stream.zig").FixedBufferStream; /// Deprecated in favor of `Reader`. pub const fixedBufferStream = @import("Io/fixed_buffer_stream.zig").fixedBufferStream; -/// Deprecated with no replacement; inefficient pattern -pub const CountingReader = @import("Io/counting_reader.zig").CountingReader; -/// Deprecated with no replacement; inefficient pattern -pub const countingReader = @import("Io/counting_reader.zig").countingReader; pub const tty = @import("Io/tty.zig"); @@ -750,7 +746,6 @@ pub fn PollFiles(comptime StreamEnum: type) type { test { _ = Reader; _ = Writer; - _ = CountingReader; _ = FixedBufferStream; _ = tty; _ = @import("Io/test.zig"); diff --git a/lib/std/Io/counting_reader.zig b/lib/std/Io/counting_reader.zig deleted file mode 100644 index bc1e1b6ec724..000000000000 --- a/lib/std/Io/counting_reader.zig +++ /dev/null @@ -1,43 +0,0 @@ -const std = @import("../std.zig"); -const io = std.io; -const testing = std.testing; - -/// A Reader that counts how many bytes has been read from it. -pub fn CountingReader(comptime ReaderType: anytype) type { - return struct { - child_reader: ReaderType, - bytes_read: u64 = 0, - - pub const Error = ReaderType.Error; - pub const Reader = io.GenericReader(*@This(), Error, read); - - pub fn read(self: *@This(), buf: []u8) Error!usize { - const amt = try self.child_reader.read(buf); - self.bytes_read += amt; - return amt; - } - - pub fn reader(self: *@This()) Reader { - return .{ .context = self }; - } - }; -} - -pub fn countingReader(reader: anytype) CountingReader(@TypeOf(reader)) { - return .{ .child_reader = reader }; -} - -test CountingReader { - const bytes = "yay" ** 100; - var fbs = io.fixedBufferStream(bytes); - - var counting_stream = countingReader(fbs.reader()); - const stream = counting_stream.reader(); - - //read and discard all bytes - while (stream.readByte()) |_| {} else |err| { - try testing.expect(err == error.EndOfStream); - } - - try testing.expect(counting_stream.bytes_read == bytes.len); -} diff --git a/src/arch/x86_64/Disassembler.zig b/src/arch/x86_64/Disassembler.zig index 545f6c0e9675..1625cd84e86a 100644 --- a/src/arch/x86_64/Disassembler.zig +++ b/src/arch/x86_64/Disassembler.zig @@ -17,12 +17,16 @@ const Rex = encoder.Rex; pub const Error = error{ EndOfStream, + /// After the TODO below is solved this will make sense. + ReadFailed, LegacyPrefixAfterRex, UnknownOpcode, Overflow, Todo, }; +// TODO these fields should be replaced by std.Io.Reader + code: []const u8, pos: usize = 0, @@ -388,20 +392,20 @@ fn parseGpRegister(low_enc: u3, is_extended: bool, rex: Rex, bit_size: u64) Regi } fn parseImm(dis: *Disassembler, kind: Encoding.Op) !Immediate { - var stream = std.io.fixedBufferStream(dis.code[dis.pos..]); - var creader = std.io.countingReader(stream.reader()); - const reader = creader.reader(); + var reader: std.Io.Reader = .fixed(dis.code); + reader.seek = dis.pos; + defer dis.pos = reader.seek; + const imm = switch (kind) { - .imm8s, .rel8 => Immediate.s(try reader.readInt(i8, .little)), - .imm16s, .rel16 => Immediate.s(try reader.readInt(i16, .little)), - .imm32s, .rel32 => Immediate.s(try reader.readInt(i32, .little)), - .imm8 => Immediate.u(try reader.readInt(u8, .little)), - .imm16 => Immediate.u(try reader.readInt(u16, .little)), - .imm32 => Immediate.u(try reader.readInt(u32, .little)), - .imm64 => Immediate.u(try reader.readInt(u64, .little)), + .imm8s, .rel8 => Immediate.s(try reader.takeInt(i8, .little)), + .imm16s, .rel16 => Immediate.s(try reader.takeInt(i16, .little)), + .imm32s, .rel32 => Immediate.s(try reader.takeInt(i32, .little)), + .imm8 => Immediate.u(try reader.takeInt(u8, .little)), + .imm16 => Immediate.u(try reader.takeInt(u16, .little)), + .imm32 => Immediate.u(try reader.takeInt(u32, .little)), + .imm64 => Immediate.u(try reader.takeInt(u64, .little)), else => unreachable, }; - dis.pos += std.math.cast(usize, creader.bytes_read) orelse return error.Overflow; return imm; } @@ -483,25 +487,25 @@ fn parseSibByte(dis: *Disassembler) !Sib { } fn parseDisplacement(dis: *Disassembler, modrm: ModRm, sib: ?Sib) !i32 { - var stream = std.io.fixedBufferStream(dis.code[dis.pos..]); - var creader = std.io.countingReader(stream.reader()); - const reader = creader.reader(); + var reader: std.Io.Reader = .fixed(dis.code); + reader.seek = dis.pos; + defer dis.pos = reader.seek; + const disp = disp: { if (sib) |info| { if (info.base == 0b101 and modrm.mod == 0) { - break :disp try reader.readInt(i32, .little); + break :disp try reader.takeInt(i32, .little); } } if (modrm.rip()) { - break :disp try reader.readInt(i32, .little); + break :disp try reader.takeInt(i32, .little); } break :disp switch (modrm.mod) { 0b00 => 0, - 0b01 => try reader.readInt(i8, .little), - 0b10 => try reader.readInt(i32, .little), + 0b01 => try reader.takeInt(i8, .little), + 0b10 => try reader.takeInt(i32, .little), 0b11 => unreachable, }; }; - dis.pos += std.math.cast(usize, creader.bytes_read) orelse return error.Overflow; return disp; } diff --git a/src/link/MachO/Dwarf.zig b/src/link/MachO/Dwarf.zig index fdc3f33bbce8..85757ead7bc6 100644 --- a/src/link/MachO/Dwarf.zig +++ b/src/link/MachO/Dwarf.zig @@ -273,19 +273,19 @@ pub const InfoReader = struct { } pub fn readUleb128(p: *InfoReader, comptime Type: type) !Type { - var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]); - var creader = std.io.countingReader(stream.reader()); - const value: Type = try leb.readUleb128(Type, creader.reader()); - p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; - return value; + var reader: std.Io.Reader = .fixed(p.bytes()); + reader.seek = p.pos; + defer p.pos = reader.seek; + + return reader.takeLeb128(Type); } pub fn readIleb128(p: *InfoReader, comptime Type: type) !Type { - var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]); - var creader = std.io.countingReader(stream.reader()); - const value: Type = try leb.readIleb128(Type, creader.reader()); - p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; - return value; + var reader: std.Io.Reader = .fixed(p.bytes()); + reader.seek = p.pos; + defer p.pos = reader.seek; + + return reader.takeLeb128(Type); } pub fn seekTo(p: *InfoReader, off: u64) !void { @@ -340,11 +340,11 @@ pub const AbbrevReader = struct { } pub fn readUleb128(p: *AbbrevReader, comptime Type: type) !Type { - var stream = std.io.fixedBufferStream(p.bytes()[p.pos..]); - var creader = std.io.countingReader(stream.reader()); - const value: Type = try leb.readUleb128(Type, creader.reader()); - p.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; - return value; + var reader: std.Io.Reader = .fixed(p.bytes()); + reader.seek = p.pos; + defer p.pos = reader.seek; + + return reader.takeLeb128(Type); } pub fn seekTo(p: *AbbrevReader, off: u64) !void { diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index 8dda3a74ac7c..497e1d6c4598 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -159,42 +159,18 @@ fn parseBinary(self: *Dylib, macho_file: *MachO) !void { } const TrieIterator = struct { - data: []const u8, - pos: usize = 0, - - fn getStream(it: *TrieIterator) std.io.FixedBufferStream([]const u8) { - return std.io.fixedBufferStream(it.data[it.pos..]); - } + stream: std.Io.Reader, fn readUleb128(it: *TrieIterator) !u64 { - var stream = it.getStream(); - var creader = std.io.countingReader(stream.reader()); - const reader = creader.reader(); - const value = try std.leb.readUleb128(u64, reader); - it.pos += math.cast(usize, creader.bytes_read) orelse return error.Overflow; - return value; + return it.stream.takeLeb128(u64); } fn readString(it: *TrieIterator) ![:0]const u8 { - var stream = it.getStream(); - const reader = stream.reader(); - - var count: usize = 0; - while (true) : (count += 1) { - const byte = try reader.readByte(); - if (byte == 0) break; - } - - const str = @as([*:0]const u8, @ptrCast(it.data.ptr + it.pos))[0..count :0]; - it.pos += count + 1; - return str; + return it.stream.takeSentinel(0); } fn readByte(it: *TrieIterator) !u8 { - var stream = it.getStream(); - const value = try stream.reader().readByte(); - it.pos += 1; - return value; + return it.stream.takeByte(); } }; @@ -243,10 +219,10 @@ fn parseTrieNode( const label = try it.readString(); const off = try it.readUleb128(); const prefix_label = try std.fmt.allocPrint(arena, "{s}{s}", .{ prefix, label }); - const curr = it.pos; - it.pos = math.cast(usize, off) orelse return error.Overflow; + const curr = it.stream.seek; + it.stream.seek = math.cast(usize, off) orelse return error.Overflow; try self.parseTrieNode(it, allocator, arena, prefix_label); - it.pos = curr; + it.stream.seek = curr; } } @@ -257,7 +233,7 @@ fn parseTrie(self: *Dylib, data: []const u8, macho_file: *MachO) !void { var arena = std.heap.ArenaAllocator.init(gpa); defer arena.deinit(); - var it: TrieIterator = .{ .data = data }; + var it: TrieIterator = .{ .stream = .fixed(data) }; try self.parseTrieNode(&it, gpa, arena.allocator(), ""); } diff --git a/src/link/MachO/eh_frame.zig b/src/link/MachO/eh_frame.zig index 9252dd83f4d7..b69fc505e293 100644 --- a/src/link/MachO/eh_frame.zig +++ b/src/link/MachO/eh_frame.zig @@ -17,31 +17,29 @@ pub const Cie = struct { if (aug[0] != 'z') return; // TODO should we error out? - var stream = std.io.fixedBufferStream(data[9 + aug.len + 1 ..]); - var creader = std.io.countingReader(stream.reader()); - const reader = creader.reader(); + var reader: std.Io.Reader = .fixed(data[9 + aug.len + 1 ..]); - _ = try leb.readUleb128(u64, reader); // code alignment factor - _ = try leb.readUleb128(u64, reader); // data alignment factor - _ = try leb.readUleb128(u64, reader); // return address register - _ = try leb.readUleb128(u64, reader); // augmentation data length + _ = try reader.takeLeb128(u64); // code alignment factor + _ = try reader.takeLeb128(u64); // data alignment factor + _ = try reader.takeLeb128(u64); // return address register + _ = try reader.takeLeb128(u64); // augmentation data length for (aug[1..]) |ch| switch (ch) { 'R' => { - const enc = try reader.readByte(); + const enc = try reader.takeByte(); if (enc != DW_EH_PE.pcrel | DW_EH_PE.absptr) { @panic("unexpected pointer encoding"); // TODO error } }, 'P' => { - const enc = try reader.readByte(); + const enc = try reader.takeByte(); if (enc != DW_EH_PE.pcrel | DW_EH_PE.indirect | DW_EH_PE.sdata4) { @panic("unexpected personality pointer encoding"); // TODO error } - _ = try reader.readInt(u32, .little); // personality pointer + _ = try reader.takeInt(u32, .little); // personality pointer }, 'L' => { - const enc = try reader.readByte(); + const enc = try reader.takeByte(); switch (enc & DW_EH_PE.type_mask) { DW_EH_PE.sdata4 => cie.lsda_size = .p32, DW_EH_PE.absptr => cie.lsda_size = .p64, @@ -163,14 +161,13 @@ pub const Fde = struct { // Parse LSDA atom index if any if (cie.lsda_size) |lsda_size| { - var stream = std.io.fixedBufferStream(data[24..]); - var creader = std.io.countingReader(stream.reader()); - const reader = creader.reader(); - _ = try leb.readUleb128(u64, reader); // augmentation length - fde.lsda_ptr_offset = @intCast(creader.bytes_read + 24); + var reader: std.Io.Reader = .fixed(data); + reader.seek = 24; + _ = try reader.takeLeb128(u64); // augmentation length + fde.lsda_ptr_offset = @intCast(reader.seek); const lsda_ptr = switch (lsda_size) { - .p32 => try reader.readInt(i32, .little), - .p64 => try reader.readInt(i64, .little), + .p32 => try reader.takeInt(i32, .little), + .p64 => try reader.takeInt(i64, .little), }; const lsda_addr: u64 = @intCast(@as(i64, @intCast(sect.addr + fde.offset + fde.lsda_ptr_offset)) + lsda_ptr); fde.lsda = object.findAtom(lsda_addr) orelse {