authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-28 21:05:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-31 22:10:11-07:00
log2569f4ff8514f47730c1abd42691f8fc1cdd22d5
treeeee17566aac40aef7f0ba12a44869bc7d42bdbc0
parent5bc63794cc9f38801e674d306c2c9ef4ccf92f13

simplify tossBitsEnding


1 files changed, 30 insertions(+), 18 deletions(-)

lib/std/compress/flate/Decompress.zig+30-18
...@@ -219,7 +219,7 @@ fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.S...@@ -219,7 +219,7 @@ fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.S
219 const block_type: BlockType = @enumFromInt(try d.takeBits(u2));219 const block_type: BlockType = @enumFromInt(try d.takeBits(u2));
220 switch (block_type) {220 switch (block_type) {
221 .stored => {221 .stored => {
222 d.alignBitsToByte(); // skip padding until byte boundary222 d.alignBitsDiscarding();
223 // everything after this is byte aligned in stored block223 // everything after this is byte aligned in stored block
224 const len = try in.takeInt(u16, .little);224 const len = try in.takeInt(u16, .little);
225 const nlen = try in.takeInt(u16, .little);225 const nlen = try in.takeInt(u16, .little);
...@@ -333,20 +333,23 @@ fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.S...@@ -333,20 +333,23 @@ fn readInner(d: *Decompress, w: *Writer, limit: std.Io.Limit) (Error || Reader.S
333 return @intFromEnum(limit) - remaining;333 return @intFromEnum(limit) - remaining;
334 },334 },
335 .protocol_footer => {335 .protocol_footer => {
336 d.alignBitsToByte();
337 switch (d.container_metadata) {336 switch (d.container_metadata) {
338 .gzip => |*gzip| {337 .gzip => |*gzip| {
338 d.alignBitsDiscarding();
339 gzip.* = .{339 gzip.* = .{
340 .crc = try in.takeInt(u32, .little),340 .crc = try in.takeInt(u32, .little),
341 .count = try in.takeInt(u32, .little),341 .count = try in.takeInt(u32, .little),
342 };342 };
343 },343 },
344 .zlib => |*zlib| {344 .zlib => |*zlib| {
345 d.alignBitsDiscarding();
345 zlib.* = .{346 zlib.* = .{
346 .adler = try in.takeInt(u32, .little),347 .adler = try in.takeInt(u32, .little),
347 };348 };
348 },349 },
349 .raw => {},350 .raw => {
351 d.alignBitsPreserving();
352 },
350 }353 }
351 d.state = .end;354 d.state = .end;
352 return 0;355 return 0;
...@@ -475,22 +478,16 @@ fn tossBits(d: *Decompress, n: u6) !void {...@@ -475,22 +478,16 @@ fn tossBits(d: *Decompress, n: u6) !void {
475fn tossBitsEnding(d: *Decompress, n: u6) !void {478fn tossBitsEnding(d: *Decompress, n: u6) !void {
476 const remaining_bits = d.remaining_bits;479 const remaining_bits = d.remaining_bits;
477 const in = d.input;480 const in = d.input;
478 var remaining_needed_bits = n - remaining_bits;481 const buffered_n = in.bufferedLen();
479 while (remaining_needed_bits >= 8) {482 if (buffered_n == 0) return error.EndOfStream;
480 try in.discardAll(1);483 assert(buffered_n < @sizeOf(usize));
481 remaining_needed_bits -= 8;484 const needed_bits = n - remaining_bits;
482 }485 const next_int = in.takeVarInt(usize, .little, buffered_n) catch |err| switch (err) {
483 if (remaining_needed_bits == 0) {
484 d.next_bits = 0;
485 d.remaining_bits = 0;
486 return;
487 }
488 const byte = in.takeByte() catch |err| switch (err) {
489 error.ReadFailed => return error.ReadFailed,486 error.ReadFailed => return error.ReadFailed,
490 error.EndOfStream => if (remaining_bits == 0) return error.EndOfStream else 0,487 error.EndOfStream => unreachable,
491 };488 };
492 d.next_bits = @as(usize, byte) >> remaining_needed_bits;489 d.next_bits = next_int >> needed_bits;
493 d.remaining_bits = @intCast(8 - remaining_needed_bits);490 d.remaining_bits = @intCast(@as(usize, n) * 8 -| @as(usize, needed_bits));
494}491}
495492
496fn takeBitsRuntime(d: *Decompress, n: u4) !u16 {493fn takeBitsRuntime(d: *Decompress, n: u4) !u16 {
...@@ -501,7 +498,7 @@ fn takeBitsRuntime(d: *Decompress, n: u4) !u16 {...@@ -501,7 +498,7 @@ fn takeBitsRuntime(d: *Decompress, n: u4) !u16 {
501 return u;498 return u;
502}499}
503500
504fn alignBitsToByte(d: *Decompress) void {501fn alignBitsDiscarding(d: *Decompress) void {
505 const remaining_bits = d.remaining_bits;502 const remaining_bits = d.remaining_bits;
506 const next_bits = d.next_bits;503 const next_bits = d.next_bits;
507 if (remaining_bits == 0) return;504 if (remaining_bits == 0) return;
...@@ -518,6 +515,21 @@ fn alignBitsToByte(d: *Decompress) void {...@@ -518,6 +515,21 @@ fn alignBitsToByte(d: *Decompress) void {
518 d.next_bits = 0;515 d.next_bits = 0;
519}516}
520517
518fn alignBitsPreserving(d: *Decompress) void {
519 const remaining_bits: usize = d.remaining_bits;
520 if (remaining_bits == 0) return;
521 const n_bytes = (remaining_bits + 7) / 8;
522 const in = d.input;
523 in.seek -= n_bytes;
524 var put_back_bits = d.next_bits;
525 for (in.buffer[in.seek..][0..n_bytes]) |*b| {
526 b.* = @truncate(put_back_bits);
527 put_back_bits >>= 8;
528 }
529 d.remaining_bits = 0;
530 d.next_bits = 0;
531}
532
521/// Reads first 7 bits, and then maybe 1 or 2 more to get full 7,8 or 9 bit code.533/// Reads first 7 bits, and then maybe 1 or 2 more to get full 7,8 or 9 bit code.
522/// ref: https://datatracker.ietf.org/doc/html/rfc1951#page-12534/// ref: https://datatracker.ietf.org/doc/html/rfc1951#page-12
523/// Lit Value Bits Codes535/// Lit Value Bits Codes