Commit 558bea2a76

Andrew Kelley <andrew@ziglang.org>
2025-08-28 04:51:12
std.Io: delete CountingReader
1 parent 4b948e8
Changed files (7)
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;
             }
         }
 
lib/std/Io/counting_reader.zig
@@ -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);
-}
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");
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;
 }
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 {
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(), "");
 }
 
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 {