authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-01 09:04:27-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-01 09:04:27-07:00
loga6f7927764fde807cb077fb4385be0729035e1db
treebebab305596d579e6383b0ed2aa00d3403cd20b3
parenteb17d4562a6515baa7128eb4cd3ffdab3e6c4835

std.compress.flate.Decompress: use 64 buffered bits

will have to find out why usize doesn't work for 32 bit targets some other time

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

lib/std/compress/flate/Decompress.zig+21-18
......@@ -10,8 +10,8 @@ const Decompress = @This();
1010const Token = @import("Token.zig");
1111
1212input: *Reader,
13next_bits: usize,
14remaining_bits: std.math.Log2Int(usize),
13next_bits: Bits,
14remaining_bits: std.math.Log2Int(Bits),
1515
1616reader: Reader,
1717
......@@ -25,6 +25,9 @@ state: State,
2525
2626err: ?Error,
2727
28/// TODO: change this to usize
29const Bits = u64;
30
2831const BlockType = enum(u2) {
2932 stored = 0,
3033 fixed = 1,
......@@ -498,14 +501,14 @@ fn takeBits(d: *Decompress, comptime U: type) !U {
498501 return u;
499502 }
500503 const in = d.input;
501 const next_int = in.takeInt(usize, .little) catch |err| switch (err) {
504 const next_int = in.takeInt(Bits, .little) catch |err| switch (err) {
502505 error.ReadFailed => return error.ReadFailed,
503506 error.EndOfStream => return takeBitsEnding(d, U),
504507 };
505508 const needed_bits = @bitSizeOf(U) - remaining_bits;
506 const u: U = @intCast(((next_int & ((@as(usize, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
509 const u: U = @intCast(((next_int & ((@as(Bits, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
507510 d.next_bits = next_int >> needed_bits;
508 d.remaining_bits = @intCast(@bitSizeOf(usize) - @as(usize, needed_bits));
511 d.remaining_bits = @intCast(@bitSizeOf(Bits) - @as(usize, needed_bits));
509512 return u;
510513}
511514
......@@ -514,14 +517,14 @@ fn takeBitsEnding(d: *Decompress, comptime U: type) !U {
514517 const next_bits = d.next_bits;
515518 const in = d.input;
516519 const n = in.bufferedLen();
517 assert(n < @sizeOf(usize));
520 assert(n < @sizeOf(Bits));
518521 const needed_bits = @bitSizeOf(U) - remaining_bits;
519522 if (n * 8 < needed_bits) return error.EndOfStream;
520 const next_int = in.takeVarInt(usize, .little, n) catch |err| switch (err) {
523 const next_int = in.takeVarInt(Bits, .little, n) catch |err| switch (err) {
521524 error.ReadFailed => return error.ReadFailed,
522525 error.EndOfStream => unreachable,
523526 };
524 const u: U = @intCast(((next_int & ((@as(usize, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
527 const u: U = @intCast(((next_int & ((@as(Bits, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
525528 d.next_bits = next_int >> needed_bits;
526529 d.remaining_bits = @intCast(n * 8 - @as(usize, needed_bits));
527530 return u;
......@@ -532,37 +535,37 @@ fn peekBits(d: *Decompress, comptime U: type) !U {
532535 const next_bits = d.next_bits;
533536 if (remaining_bits >= @bitSizeOf(U)) return @truncate(next_bits);
534537 const in = d.input;
535 const next_int = in.peekInt(usize, .little) catch |err| switch (err) {
538 const next_int = in.peekInt(Bits, .little) catch |err| switch (err) {
536539 error.ReadFailed => return error.ReadFailed,
537540 error.EndOfStream => return peekBitsEnding(d, U),
538541 };
539542 const needed_bits = @bitSizeOf(U) - remaining_bits;
540 return @intCast(((next_int & ((@as(usize, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
543 return @intCast(((next_int & ((@as(Bits, 1) << needed_bits) - 1)) << remaining_bits) | next_bits);
541544}
542545
543546fn peekBitsEnding(d: *Decompress, comptime U: type) !U {
544547 const remaining_bits = d.remaining_bits;
545548 const next_bits = d.next_bits;
546549 const in = d.input;
547 var u: usize = 0;
550 var u: Bits = 0;
548551 var remaining_needed_bits = @bitSizeOf(U) - remaining_bits;
549552 var i: usize = 0;
550553 while (remaining_needed_bits >= 8) {
551554 const byte = try specialPeek(in, next_bits, i);
552 u |= @as(usize, byte) << @intCast(i * 8);
555 u |= @as(Bits, byte) << @intCast(i * 8);
553556 remaining_needed_bits -= 8;
554557 i += 1;
555558 }
556559 if (remaining_needed_bits != 0) {
557560 const byte = try specialPeek(in, next_bits, i);
558 u |= @as(usize, byte) << @intCast((i * 8) + remaining_needed_bits);
561 u |= @as(Bits, byte) << @intCast((i * 8) + remaining_needed_bits);
559562 }
560563 return @truncate((u << remaining_bits) | next_bits);
561564}
562565
563566/// If there is any unconsumed data, handles EndOfStream by pretending there
564567/// are zeroes afterwards.
565fn specialPeek(in: *Reader, next_bits: usize, i: usize) Reader.Error!u8 {
568fn specialPeek(in: *Reader, next_bits: Bits, i: usize) Reader.Error!u8 {
566569 const peeked = in.peek(i + 1) catch |err| switch (err) {
567570 error.ReadFailed => return error.ReadFailed,
568571 error.EndOfStream => if (next_bits == 0 and i == 0) return error.EndOfStream else return 0,
......@@ -578,13 +581,13 @@ fn tossBits(d: *Decompress, n: u4) !void {
578581 d.remaining_bits = remaining_bits - n;
579582 } else {
580583 const in = d.input;
581 const next_int = in.takeInt(usize, .little) catch |err| switch (err) {
584 const next_int = in.takeInt(Bits, .little) catch |err| switch (err) {
582585 error.ReadFailed => return error.ReadFailed,
583586 error.EndOfStream => return tossBitsEnding(d, n),
584587 };
585588 const needed_bits = n - remaining_bits;
586589 d.next_bits = next_int >> needed_bits;
587 d.remaining_bits = @intCast(@bitSizeOf(usize) - @as(usize, needed_bits));
590 d.remaining_bits = @intCast(@bitSizeOf(Bits) - @as(usize, needed_bits));
588591 }
589592}
590593
......@@ -593,9 +596,9 @@ fn tossBitsEnding(d: *Decompress, n: u4) !void {
593596 const in = d.input;
594597 const buffered_n = in.bufferedLen();
595598 if (buffered_n == 0) return error.EndOfStream;
596 assert(buffered_n < @sizeOf(usize));
599 assert(buffered_n < @sizeOf(Bits));
597600 const needed_bits = n - remaining_bits;
598 const next_int = in.takeVarInt(usize, .little, buffered_n) catch |err| switch (err) {
601 const next_int = in.takeVarInt(Bits, .little, buffered_n) catch |err| switch (err) {
599602 error.ReadFailed => return error.ReadFailed,
600603 error.EndOfStream => unreachable,
601604 };