diff --git a/miniz_oxide/src/deflate/core.rs b/miniz_oxide/src/deflate/core.rs index 0064a51..9e9830d 100644 --- a/miniz_oxide/src/deflate/core.rs +++ b/miniz_oxide/src/deflate/core.rs @@ -1681,6 +1681,16 @@ pub(crate) fn flush_block( output.bit_buffer = d.params.saved_bit_buffer; output.bits_in = d.params.saved_bits_in; + // If we are at the start of the stream, write the zlib header + // if requested. Note: Even if block-writing is skipped + // below, `block_index` is still incremented, so this is done + // only once + if d.params.flags & TDEFL_WRITE_ZLIB_HEADER != 0 && d.params.block_index == 0 { + let header = zlib::header_from_flags(d.params.flags); + output.put_bits_no_flush(header[0].into(), 8); + output.put_bits(header[1].into(), 8); + } + if d.lz.total_bytes > 0 || flush == TDEFLFlush::Finish { // TODO: Don't think this second condition should be here but need to verify. let use_raw_block = (d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0) @@ -1696,13 +1706,6 @@ pub(crate) fn flush_block( d.lz.init_flag(); - // If we are at the start of the stream, write the zlib header if requested. - if d.params.flags & TDEFL_WRITE_ZLIB_HEADER != 0 && d.params.block_index == 0 { - let header = zlib::header_from_flags(d.params.flags); - output.put_bits_no_flush(header[0].into(), 8); - output.put_bits(header[1].into(), 8); - } - // Output the block header. output.put_bits((flush == TDEFLFlush::Finish) as u32, 1); diff --git a/miniz_oxide/tests/flush.rs b/miniz_oxide/tests/flush.rs index 795fb9e..af87be1 100644 --- a/miniz_oxide/tests/flush.rs +++ b/miniz_oxide/tests/flush.rs @@ -93,6 +93,21 @@ fn test_flush() { } } +/// Test that a sync at start of a stream inserts the Zlib header +/// correctly +#[test] +fn check_zlib_with_sync_at_start() { + // Test sync gets zlib header + compress(b"", &[TDEFLFlush::Sync]); + compress(b"", &[TDEFLFlush::Partial]); + + // Test that second sync DOESN'T get zlib header + // (i.e. `block_index` handling is correct) + compress(b"", &[TDEFLFlush::Sync, TDEFLFlush::Sync]); + compress(b"", &[TDEFLFlush::Partial, TDEFLFlush::Partial]); + compress(b"", &[TDEFLFlush::NoSync, TDEFLFlush::Sync]); +} + // Low-quality RNG, copied from test.rs struct Rng(u64);