Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add finisher drop implementation to BzEncoder #121

Merged
merged 5 commits into from
Jan 13, 2025

Conversation

jonasbb
Copy link
Contributor

@jonasbb jonasbb commented Dec 15, 2024

This ensures that finish will always be attempted to be called, for
example when operating as a Box<dyn Writer>. This existed in the 0.4 version of the crate and adding back the implementation fixes some test failures I observed after upgrading.

Without the Drop implementation the generated byte sequence ends up too short and cannot be decompressed.

@folkertdev
Copy link
Collaborator

This looks roughly correct, but could you add some test cases that are fixed by this change, so we don't regress in the future?

impl<W: Write> Drop for BzEncoder<W> {
fn drop(&mut self) {
if self.obj.is_some() {
let _ = self.try_finish();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::io::BufWriter skips the flush on Drop if a panic happened while writing to the inner writer. It does so by having a panicked field which is set to true before writing to the inner writer and set to false immediately after writing. This avoids a double panic if the inner writer would panic on the second write too.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you implying that we should be doing something similar here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to do so yeah.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand what you want me to tell here or how to apply the panicked field in this implementation.

@jonasbb
Copy link
Contributor Author

jonasbb commented Dec 16, 2024

I can add a test case to show why the Drop is relevant and to prevent regressions.

@folkertdev
Copy link
Collaborator

That would be great, we'll take it from there then.

This ensures that finish will always be attempted to be called, for
example when operating as a `Box<dyn Writer>`.
…regress

Without the `impl<W: Write> Drop for BzEncoder<W>` the test fails with
the error message:
    called `Result::unwrap()` on an `Err` value: Custom { kind: UnexpectedEof, error: "Input EOF reached before logical stream end" }
let uncompressed = {
let mut d = BzDecoder::new(Vec::new());
d.write_all(&compressed).unwrap();
d.finish().unwrap()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the Drop implementation, this line fails with:

called `Result::unwrap()` on an `Err` value: Custom { kind: UnexpectedEof, error: "Input EOF reached before logical stream end" }

@jonasbb
Copy link
Contributor Author

jonasbb commented Dec 17, 2024

I added a test for the behavior. It does fail as expected, when I remove the impl<W: Write> Drop for BzEncoder<W>.

als use a bit less memory; it's not really needed to prove the point
@folkertdev folkertdev requested a review from bjorn3 December 18, 2024 20:18
@bjorn3 bjorn3 mentioned this pull request Dec 19, 2024
@folkertdev folkertdev merged commit 09a87db into trifectatechfoundation:master Jan 13, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants