authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-28 20:28:07-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-31 22:10:11-07:00
logc00fb86db6a9d1f1eb0684304eeb79b1f12bb805
treec4ddf49a37054c6dcd1c855437ee87e3442fa0be
parent8ab91a6fe9d37ffc51645718a077b781be5d8873

fix peekBitsEnding


1 files changed, 21 insertions(+), 22 deletions(-)

lib/std/compress/flate/Decompress.zig+21-22
...@@ -139,11 +139,8 @@ fn dynamicCodeLength(self: *Decompress, code: u16, lens: []u4, pos: usize) !usiz...@@ -139,11 +139,8 @@ fn dynamicCodeLength(self: *Decompress, code: u16, lens: []u4, pos: usize) !usiz
139 }139 }
140}140}
141141
142// Peek 15 bits from bits reader (maximum code len is 15 bits). Use
143// decoder to find symbol for that code. We then know how many bits is
144// used. Shift bit reader for that much bits, those bits are used. And
145// return symbol.
146fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol {142fn decodeSymbol(self: *Decompress, decoder: anytype) !Symbol {
143 // Maximum code len is 15 bits.
147 const sym = try decoder.find(@bitReverse(try self.peekBits(u15)));144 const sym = try decoder.find(@bitReverse(try self.peekBits(u15)));
148 try self.tossBits(sym.code_bits);145 try self.tossBits(sym.code_bits);
149 return sym;146 return sym;
...@@ -451,31 +448,30 @@ fn peekBitsEnding(d: *Decompress, comptime U: type) !U {...@@ -451,31 +448,30 @@ fn peekBitsEnding(d: *Decompress, comptime U: type) !U {
451 const remaining_bits = d.remaining_bits;448 const remaining_bits = d.remaining_bits;
452 const next_bits = d.next_bits;449 const next_bits = d.next_bits;
453 const in = d.input;450 const in = d.input;
454 var u: U = 0;451 var u: usize = 0;
455 var remaining_needed_bits = @bitSizeOf(U) - remaining_bits;452 var remaining_needed_bits = @bitSizeOf(U) - remaining_bits;
456 var peek_len: usize = 0;453 var i: usize = 0;
457 while (@bitSizeOf(U) >= 8 and remaining_needed_bits >= 8) {454 while (remaining_needed_bits >= 8) {
458 peek_len += 1;455 const byte = try specialPeek(in, next_bits, i);
459 const byte = try specialPeek(in, next_bits, peek_len);456 u |= @as(usize, byte) << @intCast(i * 8);
460 u = (u << 8) | byte;
461 remaining_needed_bits -= 8;457 remaining_needed_bits -= 8;
458 i += 1;
462 }459 }
463 if (remaining_needed_bits != 0) {460 if (remaining_needed_bits != 0) {
464 peek_len += 1;461 const byte = try specialPeek(in, next_bits, i);
465 const byte = try specialPeek(in, next_bits, peek_len);462 u |= @as(usize, byte) << @intCast((i * 8) + remaining_needed_bits);
466 u = @intCast((@as(usize, u) << remaining_needed_bits) | (byte & ((@as(usize, 1) << remaining_needed_bits) - 1)));
467 }463 }
468 return @intCast((@as(usize, u) << remaining_bits) | next_bits);464 return @truncate((u << remaining_bits) | next_bits);
469}465}
470466
471/// If there is any unconsumed data, handles EndOfStream by pretending there467/// If there is any unconsumed data, handles EndOfStream by pretending there
472/// are zeroes afterwards.468/// are zeroes afterwards.
473fn specialPeek(in: *Reader, next_bits: usize, n: usize) Reader.Error!u8 {469fn specialPeek(in: *Reader, next_bits: usize, i: usize) Reader.Error!u8 {
474 const peeked = in.peek(n) catch |err| switch (err) {470 const peeked = in.peek(i + 1) catch |err| switch (err) {
475 error.ReadFailed => return error.ReadFailed,471 error.ReadFailed => return error.ReadFailed,
476 error.EndOfStream => if (next_bits == 0 and n == 0) return error.EndOfStream else return 0,472 error.EndOfStream => if (next_bits == 0 and i == 0) return error.EndOfStream else return 0,
477 };473 };
478 return peeked[n - 1];474 return peeked[i];
479}475}
480476
481fn tossBits(d: *Decompress, n: u6) !void {477fn tossBits(d: *Decompress, n: u6) !void {
...@@ -507,11 +503,14 @@ fn tossBitsEnding(d: *Decompress, n: u6) !void {...@@ -507,11 +503,14 @@ fn tossBitsEnding(d: *Decompress, n: u6) !void {
507 if (remaining_needed_bits == 0) {503 if (remaining_needed_bits == 0) {
508 d.next_bits = 0;504 d.next_bits = 0;
509 d.remaining_bits = 0;505 d.remaining_bits = 0;
510 } else {506 return;
511 const byte = try in.takeByte();
512 d.next_bits = @as(usize, byte) >> remaining_needed_bits;
513 d.remaining_bits = @intCast(8 - remaining_needed_bits);
514 }507 }
508 const byte = in.takeByte() catch |err| switch (err) {
509 error.ReadFailed => return error.ReadFailed,
510 error.EndOfStream => if (remaining_bits == 0) return error.EndOfStream else 0,
511 };
512 d.next_bits = @as(usize, byte) >> remaining_needed_bits;
513 d.remaining_bits = @intCast(8 - remaining_needed_bits);
515}514}
516515
517fn takeBitsRuntime(d: *Decompress, n: u4) !u16 {516fn takeBitsRuntime(d: *Decompress, n: u4) !u16 {