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();...@@ -10,8 +10,8 @@ const Decompress = @This();
10const Token = @import("Token.zig");10const Token = @import("Token.zig");
1111
12input: *Reader,12input: *Reader,
13next_bits: usize,13next_bits: Bits,
14remaining_bits: std.math.Log2Int(usize),14remaining_bits: std.math.Log2Int(Bits),
1515
16reader: Reader,16reader: Reader,
1717
...@@ -25,6 +25,9 @@ state: State,...@@ -25,6 +25,9 @@ state: State,
2525
26err: ?Error,26err: ?Error,
2727
28/// TODO: change this to usize
29const Bits = u64;
30
28const BlockType = enum(u2) {31const BlockType = enum(u2) {
29 stored = 0,32 stored = 0,
30 fixed = 1,33 fixed = 1,
...@@ -498,14 +501,14 @@ fn takeBits(d: *Decompress, comptime U: type) !U {...@@ -498,14 +501,14 @@ fn takeBits(d: *Decompress, comptime U: type) !U {
498 return u;501 return u;
499 }502 }
500 const in = d.input;503 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) {
502 error.ReadFailed => return error.ReadFailed,505 error.ReadFailed => return error.ReadFailed,
503 error.EndOfStream => return takeBitsEnding(d, U),506 error.EndOfStream => return takeBitsEnding(d, U),
504 };507 };
505 const needed_bits = @bitSizeOf(U) - remaining_bits;508 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);
507 d.next_bits = next_int >> needed_bits;510 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));
509 return u;512 return u;
510}513}
511514
...@@ -514,14 +517,14 @@ fn takeBitsEnding(d: *Decompress, comptime U: type) !U {...@@ -514,14 +517,14 @@ fn takeBitsEnding(d: *Decompress, comptime U: type) !U {
514 const next_bits = d.next_bits;517 const next_bits = d.next_bits;
515 const in = d.input;518 const in = d.input;
516 const n = in.bufferedLen();519 const n = in.bufferedLen();
517 assert(n < @sizeOf(usize));520 assert(n < @sizeOf(Bits));
518 const needed_bits = @bitSizeOf(U) - remaining_bits;521 const needed_bits = @bitSizeOf(U) - remaining_bits;
519 if (n * 8 < needed_bits) return error.EndOfStream;522 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) {
521 error.ReadFailed => return error.ReadFailed,524 error.ReadFailed => return error.ReadFailed,
522 error.EndOfStream => unreachable,525 error.EndOfStream => unreachable,
523 };526 };
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);
525 d.next_bits = next_int >> needed_bits;528 d.next_bits = next_int >> needed_bits;
526 d.remaining_bits = @intCast(n * 8 - @as(usize, needed_bits));529 d.remaining_bits = @intCast(n * 8 - @as(usize, needed_bits));
527 return u;530 return u;
...@@ -532,37 +535,37 @@ fn peekBits(d: *Decompress, comptime U: type) !U {...@@ -532,37 +535,37 @@ fn peekBits(d: *Decompress, comptime U: type) !U {
532 const next_bits = d.next_bits;535 const next_bits = d.next_bits;
533 if (remaining_bits >= @bitSizeOf(U)) return @truncate(next_bits);536 if (remaining_bits >= @bitSizeOf(U)) return @truncate(next_bits);
534 const in = d.input;537 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) {
536 error.ReadFailed => return error.ReadFailed,539 error.ReadFailed => return error.ReadFailed,
537 error.EndOfStream => return peekBitsEnding(d, U),540 error.EndOfStream => return peekBitsEnding(d, U),
538 };541 };
539 const needed_bits = @bitSizeOf(U) - remaining_bits;542 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);
541}544}
542545
543fn peekBitsEnding(d: *Decompress, comptime U: type) !U {546fn peekBitsEnding(d: *Decompress, comptime U: type) !U {
544 const remaining_bits = d.remaining_bits;547 const remaining_bits = d.remaining_bits;
545 const next_bits = d.next_bits;548 const next_bits = d.next_bits;
546 const in = d.input;549 const in = d.input;
547 var u: usize = 0;550 var u: Bits = 0;
548 var remaining_needed_bits = @bitSizeOf(U) - remaining_bits;551 var remaining_needed_bits = @bitSizeOf(U) - remaining_bits;
549 var i: usize = 0;552 var i: usize = 0;
550 while (remaining_needed_bits >= 8) {553 while (remaining_needed_bits >= 8) {
551 const byte = try specialPeek(in, next_bits, i);554 const byte = try specialPeek(in, next_bits, i);
552 u |= @as(usize, byte) << @intCast(i * 8);555 u |= @as(Bits, byte) << @intCast(i * 8);
553 remaining_needed_bits -= 8;556 remaining_needed_bits -= 8;
554 i += 1;557 i += 1;
555 }558 }
556 if (remaining_needed_bits != 0) {559 if (remaining_needed_bits != 0) {
557 const byte = try specialPeek(in, next_bits, i);560 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);
559 }562 }
560 return @truncate((u << remaining_bits) | next_bits);563 return @truncate((u << remaining_bits) | next_bits);
561}564}
562565
563/// If there is any unconsumed data, handles EndOfStream by pretending there566/// If there is any unconsumed data, handles EndOfStream by pretending there
564/// are zeroes afterwards.567/// 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 {
566 const peeked = in.peek(i + 1) catch |err| switch (err) {569 const peeked = in.peek(i + 1) catch |err| switch (err) {
567 error.ReadFailed => return error.ReadFailed,570 error.ReadFailed => return error.ReadFailed,
568 error.EndOfStream => if (next_bits == 0 and i == 0) return error.EndOfStream else return 0,571 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 {...@@ -578,13 +581,13 @@ fn tossBits(d: *Decompress, n: u4) !void {
578 d.remaining_bits = remaining_bits - n;581 d.remaining_bits = remaining_bits - n;
579 } else {582 } else {
580 const in = d.input;583 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) {
582 error.ReadFailed => return error.ReadFailed,585 error.ReadFailed => return error.ReadFailed,
583 error.EndOfStream => return tossBitsEnding(d, n),586 error.EndOfStream => return tossBitsEnding(d, n),
584 };587 };
585 const needed_bits = n - remaining_bits;588 const needed_bits = n - remaining_bits;
586 d.next_bits = next_int >> needed_bits;589 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));
588 }591 }
589}592}
590593
...@@ -593,9 +596,9 @@ fn tossBitsEnding(d: *Decompress, n: u4) !void {...@@ -593,9 +596,9 @@ fn tossBitsEnding(d: *Decompress, n: u4) !void {
593 const in = d.input;596 const in = d.input;
594 const buffered_n = in.bufferedLen();597 const buffered_n = in.bufferedLen();
595 if (buffered_n == 0) return error.EndOfStream;598 if (buffered_n == 0) return error.EndOfStream;
596 assert(buffered_n < @sizeOf(usize));599 assert(buffered_n < @sizeOf(Bits));
597 const needed_bits = n - remaining_bits;600 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) {
599 error.ReadFailed => return error.ReadFailed,602 error.ReadFailed => return error.ReadFailed,
600 error.EndOfStream => unreachable,603 error.EndOfStream => unreachable,
601 };604 };