| ... | @@ -372,7 +372,10 @@ fn takeBits(d: *Decompress, comptime T: type) !T { | ... | @@ -372,7 +372,10 @@ fn takeBits(d: *Decompress, comptime T: type) !T { |
| 372 | }; | 372 | }; |
| 373 | } | 373 | } |
| 374 | const in = d.input; | 374 | const in = d.input; |
| 375 | const next_int = try in.takeInt(usize, .little); | 375 | const next_int = in.takeInt(usize, .little) catch |err| switch (err) { |
| | 376 | error.ReadFailed => return error.ReadFailed, |
| | 377 | error.EndOfStream => return takeBitsEnding(d, T), |
| | 378 | }; |
| 376 | const needed_bits = @bitSizeOf(T) - remaining_bits; | 379 | const needed_bits = @bitSizeOf(T) - remaining_bits; |
| 377 | const u: U = @intCast((next_bits << needed_bits) | (next_int & ((@as(usize, 1) << needed_bits) - 1))); | 380 | const u: U = @intCast((next_bits << needed_bits) | (next_int & ((@as(usize, 1) << needed_bits) - 1))); |
| 378 | d.next_bits = next_int >> needed_bits; | 381 | d.next_bits = next_int >> needed_bits; |
| ... | @@ -384,6 +387,35 @@ fn takeBits(d: *Decompress, comptime T: type) !T { | ... | @@ -384,6 +387,35 @@ fn takeBits(d: *Decompress, comptime T: type) !T { |
| 384 | }; | 387 | }; |
| 385 | } | 388 | } |
| 386 | | 389 | |
| | 390 | fn takeBitsEnding(d: *Decompress, comptime T: type) !T { |
| | 391 | const remaining_bits = d.remaining_bits; |
| | 392 | const next_bits = d.next_bits; |
| | 393 | const in = d.input; |
| | 394 | const U = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); |
| | 395 | var u: U = 0; |
| | 396 | var remaining_needed_bits = @bitSizeOf(U) - remaining_bits; |
| | 397 | while (@bitSizeOf(U) >= 8 and remaining_needed_bits >= 8) { |
| | 398 | const byte = try in.takeByte(); |
| | 399 | u = (u << 8) | byte; |
| | 400 | remaining_needed_bits -= 8; |
| | 401 | } |
| | 402 | if (remaining_needed_bits == 0) { |
| | 403 | d.next_bits = 0; |
| | 404 | d.remaining_bits = 0; |
| | 405 | } else { |
| | 406 | const byte = try in.takeByte(); |
| | 407 | u = @intCast((@as(usize, u) << remaining_needed_bits) | (byte & ((@as(usize, 1) << remaining_needed_bits) - 1))); |
| | 408 | d.next_bits = @as(usize, byte) >> remaining_needed_bits; |
| | 409 | d.remaining_bits = @intCast(8 - remaining_needed_bits); |
| | 410 | } |
| | 411 | u = @intCast((@as(usize, u) << remaining_bits) | next_bits); |
| | 412 | return switch (@typeInfo(T)) { |
| | 413 | .int => u, |
| | 414 | .@"enum" => @enumFromInt(u), |
| | 415 | else => @bitCast(u), |
| | 416 | }; |
| | 417 | } |
| | 418 | |
| 387 | fn peekBits(d: *Decompress, comptime T: type) !T { | 419 | fn peekBits(d: *Decompress, comptime T: type) !T { |
| 388 | const U = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); | 420 | const U = @Type(.{ .int = .{ .signedness = .unsigned, .bits = @bitSizeOf(T) } }); |
| 389 | const remaining_bits = d.remaining_bits; | 421 | const remaining_bits = d.remaining_bits; |
| ... | @@ -397,7 +429,10 @@ fn peekBits(d: *Decompress, comptime T: type) !T { | ... | @@ -397,7 +429,10 @@ fn peekBits(d: *Decompress, comptime T: type) !T { |
| 397 | }; | 429 | }; |
| 398 | } | 430 | } |
| 399 | const in = d.input; | 431 | const in = d.input; |
| 400 | const next_int = try in.peekInt(usize, .little); | 432 | const next_int = in.peekInt(usize, .little) catch |err| switch (err) { |
| | 433 | error.ReadFailed => return error.ReadFailed, |
| | 434 | error.EndOfStream => return peekBitsEnding(d, T), |
| | 435 | }; |
| 401 | const needed_bits = @bitSizeOf(T) - remaining_bits; | 436 | const needed_bits = @bitSizeOf(T) - remaining_bits; |
| 402 | const u: U = @intCast((next_bits << needed_bits) | (next_int & ((@as(usize, 1) << needed_bits) - 1))); | 437 | const u: U = @intCast((next_bits << needed_bits) | (next_int & ((@as(usize, 1) << needed_bits) - 1))); |
| 403 | return switch (@typeInfo(T)) { | 438 | return switch (@typeInfo(T)) { |
| ... | @@ -407,6 +442,11 @@ fn peekBits(d: *Decompress, comptime T: type) !T { | ... | @@ -407,6 +442,11 @@ fn peekBits(d: *Decompress, comptime T: type) !T { |
| 407 | }; | 442 | }; |
| 408 | } | 443 | } |
| 409 | | 444 | |
| | 445 | fn peekBitsEnding(d: *Decompress, comptime T: type) !T { |
| | 446 | _ = d; |
| | 447 | @panic("TODO"); |
| | 448 | } |
| | 449 | |
| 410 | fn tossBits(d: *Decompress, n: u6) !void { | 450 | fn tossBits(d: *Decompress, n: u6) !void { |
| 411 | const remaining_bits = d.remaining_bits; | 451 | const remaining_bits = d.remaining_bits; |
| 412 | const next_bits = d.next_bits; | 452 | const next_bits = d.next_bits; |
| ... | @@ -415,13 +455,22 @@ fn tossBits(d: *Decompress, n: u6) !void { | ... | @@ -415,13 +455,22 @@ fn tossBits(d: *Decompress, n: u6) !void { |
| 415 | d.remaining_bits = remaining_bits - n; | 455 | d.remaining_bits = remaining_bits - n; |
| 416 | } else { | 456 | } else { |
| 417 | const in = d.input; | 457 | const in = d.input; |
| 418 | const next_int = try in.takeInt(usize, .little); | 458 | const next_int = in.takeInt(usize, .little) catch |err| switch (err) { |
| | 459 | error.ReadFailed => return error.ReadFailed, |
| | 460 | error.EndOfStream => return tossBitsEnding(d, n), |
| | 461 | }; |
| 419 | const needed_bits = n - remaining_bits; | 462 | const needed_bits = n - remaining_bits; |
| 420 | d.next_bits = next_int >> needed_bits; | 463 | d.next_bits = next_int >> needed_bits; |
| 421 | d.remaining_bits = @intCast(@bitSizeOf(usize) - @as(usize, needed_bits)); | 464 | d.remaining_bits = @intCast(@bitSizeOf(usize) - @as(usize, needed_bits)); |
| 422 | } | 465 | } |
| 423 | } | 466 | } |
| 424 | | 467 | |
| | 468 | fn tossBitsEnding(d: *Decompress, n: u6) !void { |
| | 469 | _ = d; |
| | 470 | _ = n; |
| | 471 | @panic("TODO"); |
| | 472 | } |
| | 473 | |
| 425 | fn takeNBitsBuffered(d: *Decompress, n: u4) !u16 { | 474 | fn takeNBitsBuffered(d: *Decompress, n: u4) !u16 { |
| 426 | _ = d; | 475 | _ = d; |
| 427 | _ = n; | 476 | _ = n; |