authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-27 16:16:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-31 22:10:11-07:00
log1b43551190fc9aa83ae175e1db3a9db60dba5bb9
tree486bc95ff67760a0b4de291cc9505b99dd610147
parent824c157e0c25a9337ffd036f7ad5cb811b1f18cd

std.Io: remove BitWriter


4 files changed, 0 insertions(+), 241 deletions(-)

lib/std/Io.zig-4
......@@ -470,9 +470,6 @@ pub const countingReader = @import("Io/counting_reader.zig").countingReader;
470470pub const BitReader = @import("Io/bit_reader.zig").BitReader;
471471pub const bitReader = @import("Io/bit_reader.zig").bitReader;
472472
473pub const BitWriter = @import("Io/bit_writer.zig").BitWriter;
474pub const bitWriter = @import("Io/bit_writer.zig").bitWriter;
475
476473pub const tty = @import("Io/tty.zig");
477474
478475/// Deprecated in favor of `Writer.Discarding`.
......@@ -951,7 +948,6 @@ test {
951948 _ = Reader.Limited;
952949 _ = Writer;
953950 _ = BitReader;
954 _ = BitWriter;
955951 _ = BufferedReader;
956952 _ = BufferedWriter;
957953 _ = CountingWriter;
lib/std/Io/bit_writer.zig deleted-179
......@@ -1,179 +0,0 @@
1const std = @import("../std.zig");
2
3//General note on endianess:
4//Big endian is packed starting in the most significant part of the byte and subsequent
5// bytes contain less significant bits. Thus we write out bits from the high end
6// of our input first.
7//Little endian is packed starting in the least significant part of the byte and
8// subsequent bytes contain more significant bits. Thus we write out bits from
9// the low end of our input first.
10//Regardless of endianess, within any given byte the bits are always in most
11// to least significant order.
12//Also regardless of endianess, the buffer always aligns bits to the low end
13// of the byte.
14
15/// Creates a bit writer which allows for writing bits to an underlying standard writer
16pub fn BitWriter(comptime endian: std.builtin.Endian, comptime Writer: type) type {
17 return struct {
18 writer: Writer,
19 bits: u8 = 0,
20 count: u4 = 0,
21
22 const low_bit_mask = [9]u8{
23 0b00000000,
24 0b00000001,
25 0b00000011,
26 0b00000111,
27 0b00001111,
28 0b00011111,
29 0b00111111,
30 0b01111111,
31 0b11111111,
32 };
33
34 /// Write the specified number of bits to the writer from the least significant bits of
35 /// the specified value. Bits will only be written to the writer when there
36 /// are enough to fill a byte.
37 pub fn writeBits(self: *@This(), value: anytype, num: u16) !void {
38 const T = @TypeOf(value);
39 const UT = std.meta.Int(.unsigned, @bitSizeOf(T));
40 const U = if (@bitSizeOf(T) < 8) u8 else UT; //<u8 is a pain to work with
41
42 var in: U = @as(UT, @bitCast(value));
43 var in_count: u16 = num;
44
45 if (self.count > 0) {
46 //if we can't fill the buffer, add what we have
47 const bits_free = 8 - self.count;
48 if (num < bits_free) {
49 self.addBits(@truncate(in), @intCast(num));
50 return;
51 }
52
53 //finish filling the buffer and flush it
54 if (num == bits_free) {
55 self.addBits(@truncate(in), @intCast(num));
56 return self.flushBits();
57 }
58
59 switch (endian) {
60 .big => {
61 const bits = in >> @intCast(in_count - bits_free);
62 self.addBits(@truncate(bits), bits_free);
63 },
64 .little => {
65 self.addBits(@truncate(in), bits_free);
66 in >>= @intCast(bits_free);
67 },
68 }
69 in_count -= bits_free;
70 try self.flushBits();
71 }
72
73 //write full bytes while we can
74 const full_bytes_left = in_count / 8;
75 for (0..full_bytes_left) |_| {
76 switch (endian) {
77 .big => {
78 const bits = in >> @intCast(in_count - 8);
79 try self.writer.writeByte(@truncate(bits));
80 },
81 .little => {
82 try self.writer.writeByte(@truncate(in));
83 if (U == u8) in = 0 else in >>= 8;
84 },
85 }
86 in_count -= 8;
87 }
88
89 //save the remaining bits in the buffer
90 self.addBits(@truncate(in), @intCast(in_count));
91 }
92
93 //convenience funciton for adding bits to the buffer
94 //in the appropriate position based on endianess
95 fn addBits(self: *@This(), bits: u8, num: u4) void {
96 if (num == 8) self.bits = bits else switch (endian) {
97 .big => {
98 self.bits <<= @intCast(num);
99 self.bits |= bits & low_bit_mask[num];
100 },
101 .little => {
102 const pos = bits << @intCast(self.count);
103 self.bits |= pos;
104 },
105 }
106 self.count += num;
107 }
108
109 /// Flush any remaining bits to the writer, filling
110 /// unused bits with 0s.
111 pub fn flushBits(self: *@This()) !void {
112 if (self.count == 0) return;
113 if (endian == .big) self.bits <<= @intCast(8 - self.count);
114 try self.writer.writeByte(self.bits);
115 self.bits = 0;
116 self.count = 0;
117 }
118 };
119}
120
121pub fn bitWriter(comptime endian: std.builtin.Endian, writer: anytype) BitWriter(endian, @TypeOf(writer)) {
122 return .{ .writer = writer };
123}
124
125///////////////////////////////
126
127test "api coverage" {
128 var mem_be = [_]u8{0} ** 2;
129 var mem_le = [_]u8{0} ** 2;
130
131 var mem_out_be = std.io.fixedBufferStream(&mem_be);
132 var bit_stream_be = bitWriter(.big, mem_out_be.writer());
133
134 const testing = std.testing;
135
136 try bit_stream_be.writeBits(@as(u2, 1), 1);
137 try bit_stream_be.writeBits(@as(u5, 2), 2);
138 try bit_stream_be.writeBits(@as(u128, 3), 3);
139 try bit_stream_be.writeBits(@as(u8, 4), 4);
140 try bit_stream_be.writeBits(@as(u9, 5), 5);
141 try bit_stream_be.writeBits(@as(u1, 1), 1);
142
143 try testing.expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
144
145 mem_out_be.pos = 0;
146
147 try bit_stream_be.writeBits(@as(u15, 0b110011010000101), 15);
148 try bit_stream_be.flushBits();
149 try testing.expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
150
151 mem_out_be.pos = 0;
152 try bit_stream_be.writeBits(@as(u32, 0b110011010000101), 16);
153 try testing.expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
154
155 try bit_stream_be.writeBits(@as(u0, 0), 0);
156
157 var mem_out_le = std.io.fixedBufferStream(&mem_le);
158 var bit_stream_le = bitWriter(.little, mem_out_le.writer());
159
160 try bit_stream_le.writeBits(@as(u2, 1), 1);
161 try bit_stream_le.writeBits(@as(u5, 2), 2);
162 try bit_stream_le.writeBits(@as(u128, 3), 3);
163 try bit_stream_le.writeBits(@as(u8, 4), 4);
164 try bit_stream_le.writeBits(@as(u9, 5), 5);
165 try bit_stream_le.writeBits(@as(u1, 1), 1);
166
167 try testing.expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
168
169 mem_out_le.pos = 0;
170 try bit_stream_le.writeBits(@as(u15, 0b110011010000101), 15);
171 try bit_stream_le.flushBits();
172 try testing.expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
173
174 mem_out_le.pos = 0;
175 try bit_stream_le.writeBits(@as(u32, 0b1100110100001011), 16);
176 try testing.expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
177
178 try bit_stream_le.writeBits(@as(u0, 0), 0);
179}
lib/std/Io/test.zig-45
......@@ -57,51 +57,6 @@ test "write a file, read it, then delete it" {
5757 try tmp.dir.deleteFile(tmp_file_name);
5858}
5959
60test "BitStreams with File Stream" {
61 var tmp = tmpDir(.{});
62 defer tmp.cleanup();
63
64 const tmp_file_name = "temp_test_file.txt";
65 {
66 var file = try tmp.dir.createFile(tmp_file_name, .{});
67 defer file.close();
68
69 var bit_stream = io.bitWriter(native_endian, file.deprecatedWriter());
70
71 try bit_stream.writeBits(@as(u2, 1), 1);
72 try bit_stream.writeBits(@as(u5, 2), 2);
73 try bit_stream.writeBits(@as(u128, 3), 3);
74 try bit_stream.writeBits(@as(u8, 4), 4);
75 try bit_stream.writeBits(@as(u9, 5), 5);
76 try bit_stream.writeBits(@as(u1, 1), 1);
77 try bit_stream.flushBits();
78 }
79 {
80 var file = try tmp.dir.openFile(tmp_file_name, .{});
81 defer file.close();
82
83 var bit_stream = io.bitReader(native_endian, file.deprecatedReader());
84
85 var out_bits: u16 = undefined;
86
87 try expect(1 == try bit_stream.readBits(u2, 1, &out_bits));
88 try expect(out_bits == 1);
89 try expect(2 == try bit_stream.readBits(u5, 2, &out_bits));
90 try expect(out_bits == 2);
91 try expect(3 == try bit_stream.readBits(u128, 3, &out_bits));
92 try expect(out_bits == 3);
93 try expect(4 == try bit_stream.readBits(u8, 4, &out_bits));
94 try expect(out_bits == 4);
95 try expect(5 == try bit_stream.readBits(u9, 5, &out_bits));
96 try expect(out_bits == 5);
97 try expect(1 == try bit_stream.readBits(u1, 1, &out_bits));
98 try expect(out_bits == 1);
99
100 try expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
101 }
102 try tmp.dir.deleteFile(tmp_file_name);
103}
104
10560test "File seek ops" {
10661 var tmp = tmpDir(.{});
10762 defer tmp.cleanup();
lib/std/compress/flate/HuffmanEncoder.zig-13
......@@ -421,19 +421,6 @@ test "generate a Huffman code for the 30 possible relative distances (LZ77 dista
421421 }
422422}
423423
424test "fixedLiteralEncoder codes" {
425 var al = std.ArrayList(u8).init(testing.allocator);
426 defer al.deinit();
427 var bw = std.Io.bitWriter(.little, al.writer());
428
429 var codes: [max_num_frequencies]Code = undefined;
430 const f = fixedLiteralEncoder(&codes);
431 for (f.codes) |c| {
432 try bw.writeBits(c.code, c.len);
433 }
434 try testing.expectEqualSlices(u8, &fixed_codes, al.items);
435}
436
437424pub const fixed_codes = [_]u8{
438425 0b00001100, 0b10001100, 0b01001100, 0b11001100, 0b00101100, 0b10101100, 0b01101100, 0b11101100,
439426 0b00011100, 0b10011100, 0b01011100, 0b11011100, 0b00111100, 0b10111100, 0b01111100, 0b11111100,