diff --git a/container/src/container_common.rs b/container/src/container_common.rs index b41e771..6b3c83c 100644 --- a/container/src/container_common.rs +++ b/container/src/container_common.rs @@ -198,7 +198,7 @@ pub trait ProcessBuffer { buffer = &[]; } else { buffer = input.fill_buf().context()?; - if buffer.len() == 0 { + if buffer.is_empty() { input_complete = true } }; diff --git a/container/src/container_read.rs b/container/src/container_read.rs index 795382a..e8072ac 100644 --- a/container/src/container_read.rs +++ b/container/src/container_read.rs @@ -100,7 +100,7 @@ impl ProcessBuffer for RecreateContainerProcessor { input_complete: bool, writer: &mut impl Write, ) -> Result<()> { - if self.input_complete && (input.len() > 0 || !input_complete) { + if self.input_complete && (!input.is_empty() || !input_complete) { return Err(PreflateError::new( ExitCode::InvalidParameter, "more data provided after input_complete signaled", @@ -176,7 +176,7 @@ impl RecreateContainerProcessor { loop { match &mut self.state { DecompressionState::Start => { - if !self.input_complete && self.input.len() == 0 { + if !self.input_complete && self.input.is_empty() { break; } @@ -196,7 +196,7 @@ impl RecreateContainerProcessor { } DecompressionState::StartSegment => { // here's a good place to stop if we run out of input - if self.input.len() == 0 { + if self.input.is_empty() { break; } @@ -292,19 +292,16 @@ impl RecreateContainerProcessor { } let lepton_bytes: Vec = self.input.drain(0..*lepton_length).collect(); - match lepton_jpeg::decode_lepton( + if let Err(e) = lepton_jpeg::decode_lepton( &mut Cursor::new(&lepton_bytes), writer, &EnabledFeatures::compat_lepton_vector_read(), &DEFAULT_THREAD_POOL, ) { - Err(e) => { - return Err(PreflateError::new( - ExitCode::InvalidCompressedWrapper, - format!("JPEG Lepton decode failed: {}", e), - )); - } - Ok(_) => {} + return Err(PreflateError::new( + ExitCode::InvalidCompressedWrapper, + format!("JPEG Lepton decode failed: {}", e), + )); } self.state = DecompressionState::StartSegment; } @@ -513,23 +510,20 @@ fn webp_decompress( header: &crate::idat_parse::PngHeader, ) -> Result> { #[cfg(feature = "webp")] - match webp::Decoder::new(webp.as_slice()).decode() { - Some(result) => { - use crate::idat_parse::apply_png_filters_with_types; - use std::ops::Deref; - - let m = result.deref(); - - return Ok(apply_png_filters_with_types( - m, - header.width as usize, - header.height as usize, - if result.is_alpha() { 4 } else { 3 }, - header.color_type.bytes_per_pixel(), - &filters, - )); - } - _ => {} + if let Some(result) = webp::Decoder::new(webp.as_slice()).decode() { + use crate::idat_parse::apply_png_filters_with_types; + use std::ops::Deref; + + let m = result.deref(); + + return Ok(apply_png_filters_with_types( + m, + header.width as usize, + header.height as usize, + if result.is_alpha() { 4 } else { 3 }, + header.color_type.bytes_per_pixel(), + filters, + )); } - return err_exit_code(ExitCode::InvalidCompressedWrapper, "Webp decode failed"); + err_exit_code(ExitCode::InvalidCompressedWrapper, "Webp decode failed") } diff --git a/container/src/container_write.rs b/container/src/container_write.rs index 2e9c5e5..e5d4736 100644 --- a/container/src/container_write.rs +++ b/container/src/container_write.rs @@ -38,7 +38,7 @@ pub(crate) enum ChunkParseState { /// so we need to keep track of the IHDR chunk so we can use it later to properly /// compress the PNG data. Searching(Option), - DeflateContinue(PreflateStreamProcessor), + DeflateContinue(Box), } /// V2 variant of write_chunk_block: block content goes through the persistent Zstd encoder. @@ -55,7 +55,7 @@ pub(crate) fn write_chunk_block_v2( write_varint(encoder, chunk.corrections.len() as u32)?; write_varint(encoder, state.plain_text().text().len() as u32)?; encoder.write_all(&chunk.corrections)?; - encoder.write_all(&state.plain_text().text())?; + encoder.write_all(state.plain_text().text())?; let compressed_size = emit_compressed_block( BLOCK_COMPRESSION_ZSTD | BLOCK_TYPE_DEFLATE, @@ -68,7 +68,7 @@ pub(crate) fn write_chunk_block_v2( stats.hash_algorithm = parameters.hash_algorithm; if !state.is_done() { - return Ok((compressed_size, Some(state))); + return Ok((compressed_size, Some(*state))); } Ok((compressed_size, None)) } @@ -198,14 +198,14 @@ impl ProcessBuffer for PreflateContainerProcessor { ) -> Result<()> { use crate::container_common::COMPRESSED_WRAPPER_VERSION_2; - if self.input_complete && (input.len() > 0 || !input_complete) { + if self.input_complete && (!input.is_empty() || !input_complete) { return Err(PreflateError::new( ExitCode::InvalidParameter, "more data provided after input_complete signaled", )); } - if input.len() > 0 { + if !input.is_empty() { self.compression_stats.deflate_compressed_size += input.len() as u64; self.input_crc.update(input); self.content.extend_from_slice(input); @@ -258,7 +258,8 @@ impl ProcessBuffer for PreflateContainerProcessor { input_complete, &self.config, ) { - FindStreamResult::Found(next, chunk) => { + FindStreamResult::Found(next, chunk_box) => { + let chunk = *chunk_box; // the gap between the start and the beginning of the deflate stream // is written out as a literal block if next.start != 0 { @@ -285,7 +286,7 @@ impl ProcessBuffer for PreflateContainerProcessor { if let Some(mut state) = next_state { self.total_plain_text_seen += state.plain_text().len() as u64; state.shrink_to_dictionary(); - self.state = ChunkParseState::DeflateContinue(state); + self.state = ChunkParseState::DeflateContinue(Box::new(state)); } self.content.drain(0..next.end); @@ -359,7 +360,7 @@ impl ProcessBuffer for PreflateContainerProcessor { write_varint(encoder, res.corrections.len() as u32)?; write_varint(encoder, state.plain_text().len() as u32)?; encoder.write_all(&res.corrections)?; - encoder.write_all(&state.plain_text().text())?; + encoder.write_all(state.plain_text().text())?; let sz = emit_compressed_block( BLOCK_COMPRESSION_ZSTD | BLOCK_TYPE_DEFLATE_CONTINUE, encoder, @@ -389,7 +390,7 @@ impl ProcessBuffer for PreflateContainerProcessor { if input_complete && !self.input_complete { self.input_complete = true; - if self.content.len() > 0 { + if !self.content.is_empty() { let encoder = self.encoder.as_mut().unwrap(); write_varint(encoder, self.content.len() as u32)?; encoder.write_all(&self.content)?; @@ -478,8 +479,8 @@ fn webp_compress( let enc = webp::Encoder::new( &bitmap, match png_header.color_type { - PngColorType::RGB => webp::PixelLayout::Rgb, - PngColorType::RGBA => webp::PixelLayout::Rgba, + PngColorType::Rgb => webp::PixelLayout::Rgb, + PngColorType::Rgba => webp::PixelLayout::Rgba, }, png_header.width, png_header.height, @@ -520,15 +521,15 @@ fn webp_compress( idat.write_to_bytestream(result)?; result.write_all(&filters)?; - result.write_all(&corrections)?; + result.write_all(corrections)?; result.write_all(comp.deref())?; return Ok(()); } } - return preflate_rs::err_exit_code( + preflate_rs::err_exit_code( ExitCode::InvalidCompressedWrapper, "Webp compression not supported", - ); + ) } diff --git a/container/src/idat_parse.rs b/container/src/idat_parse.rs index ed225b0..924e3dc 100644 --- a/container/src/idat_parse.rs +++ b/container/src/idat_parse.rs @@ -103,7 +103,7 @@ fn test_idat_header_roundtrip() { png_header: Some(PngHeader { width: 5, height: 5, - color_type: PngColorType::RGB, + color_type: PngColorType::Rgb, }), }; @@ -127,19 +127,19 @@ pub struct PngHeader { #[derive(Debug, PartialEq, Copy, Clone)] pub enum PngColorType { // Grayscale = 0, - RGB = 2, + Rgb = 2, // 3 = Pallete not supported //GrayscaleAlpha = 4, - RGBA = 6, + Rgba = 6, } impl PngColorType { fn parse(byte: u8) -> Option { match byte { //0 => Some(PngColorType::Grayscale), - 2 => Some(PngColorType::RGB), + 2 => Some(PngColorType::Rgb), //4 => Some(PngColorType::GrayscaleAlpha), - 6 => Some(PngColorType::RGBA), + 6 => Some(PngColorType::Rgba), _ => None, } } @@ -148,9 +148,9 @@ impl PngColorType { pub fn bytes_per_pixel(&self) -> usize { match self { //PngColorType::Grayscale => 1, - PngColorType::RGB => 3, + PngColorType::Rgb => 3, //PngColorType::GrayscaleAlpha => 2, - PngColorType::RGBA => 4, + PngColorType::Rgba => 4, } } } @@ -184,7 +184,7 @@ pub fn parse_ihdr(ihdr_chunk: &[u8]) -> Result { }) } else { log::debug!("IHDR unsupported color type {}", ihdr_data[9]); - return err_exit_code(ExitCode::InvalidIDat, "IHDR unsupported color type"); + err_exit_code(ExitCode::InvalidIDat, "IHDR unsupported color type") } } @@ -412,8 +412,7 @@ pub fn apply_png_filters_with_types( let mut rgba = vec![0u8; target_stride]; let mut encoded = vec![0u8; target_stride]; - for row in 0..height { - let filter_type = filter_types[row]; + for (row, &filter_type) in filter_types.iter().enumerate().take(height) { let offset = row * source_stride; let scanline = if source_bbp == 3 && target_bpp == 4 { diff --git a/container/src/scan_deflate.rs b/container/src/scan_deflate.rs index 2e8375b..fb488ed 100644 --- a/container/src/scan_deflate.rs +++ b/container/src/scan_deflate.rs @@ -26,7 +26,7 @@ pub struct FoundStream { pub enum FoundStreamType { /// Deflate stream - DeflateStream(TokenPredictorParameters, PreflateStreamProcessor), + DeflateStream(TokenPredictorParameters, Box), /// PNG IDAT, which is a concatenated Zlib stream of IDAT chunks. This /// is special since the Deflate stream is split into IDAT chunks. @@ -43,11 +43,11 @@ enum Signature { Gzip, /// PNG IHDR chunk which contains the width, height of the image and color format of the image. /// We keep the parsed data around so that we know the dimensions etc of the IDAT when we find it. - IHDR, + Ihdr, /// PNG IDAT, which is a concatenated Zlib stream of IDAT chunks, each of the size given in the Vec. - IDAT, + Idat, /// JPEG start marker - JPEG, + Jpeg, } fn next_signature(src: &[u8], index: &mut usize) -> Option { @@ -72,7 +72,7 @@ fn next_signature(src: &[u8], index: &mut usize) -> Option { if sig & 0x8f20 == 0x0800 { // possible zlib signature, check to see if it is % 31 - if sig % 31 == 0 { + if sig.is_multiple_of(31) { *index = i; return Some(Signature::Zlib(0)); } @@ -81,9 +81,9 @@ fn next_signature(src: &[u8], index: &mut usize) -> Option { let s = match sig { 0x504B => Signature::ZipLocalFileHeader, 0x1F8B => Signature::Gzip, - 0x4944 => Signature::IDAT, - 0x4948 => Signature::IHDR, - 0xFFD8 => Signature::JPEG, + 0x4944 => Signature::Idat, + 0x4948 => Signature::Ihdr, + 0xFFD8 => Signature::Jpeg, _ => continue, }; @@ -95,7 +95,7 @@ fn next_signature(src: &[u8], index: &mut usize) -> Option { pub enum FindStreamResult { None, - Found(Range, FoundStream), + Found(Range, Box), ShortRead, } @@ -113,21 +113,20 @@ pub fn find_compressable_stream( Signature::Zlib(_) => { let mut state = PreflateStreamProcessor::new(&config.preflate_config()); - if let Ok(res) = state.decompress(&src[index + 2..]) { - if state.plain_text().len() > MIN_BLOCKSIZE { + if let Ok(res) = state.decompress(&src[index + 2..]) + && state.plain_text().len() > MIN_BLOCKSIZE { index += 2; return FindStreamResult::Found( index..index + res.compressed_size, - FoundStream { + Box::new(FoundStream { chunk_type: FoundStreamType::DeflateStream( res.parameters.unwrap(), - state, + Box::new(state), ), corrections: res.corrections, - }, + }), ); } - } } Signature::Gzip => { @@ -136,43 +135,40 @@ pub fn find_compressable_stream( let start = index + cursor.position() as usize; let mut state = PreflateStreamProcessor::new(&config.preflate_config()); - if let Ok(res) = state.decompress(&src[start..]) { - if state.plain_text().len() > MIN_BLOCKSIZE { + if let Ok(res) = state.decompress(&src[start..]) + && state.plain_text().len() > MIN_BLOCKSIZE { return FindStreamResult::Found( start..start + res.compressed_size, - FoundStream { + Box::new(FoundStream { chunk_type: FoundStreamType::DeflateStream( res.parameters.unwrap(), - state, + Box::new(state), ), corrections: res.corrections, - }, + }), ); } - } } } Signature::ZipLocalFileHeader => { if let Ok((header_size, res, state)) = parse_zip_stream(&src[index..], &config.preflate_config()) - { - if state.plain_text().len() > MIN_BLOCKSIZE { + && state.plain_text().len() > MIN_BLOCKSIZE { return FindStreamResult::Found( index + header_size..index + header_size + res.compressed_size, - FoundStream { + Box::new(FoundStream { chunk_type: FoundStreamType::DeflateStream( res.parameters.unwrap(), - state, + Box::new(state), ), corrections: res.corrections, - }, + }), ); } - } } - Signature::IHDR => { + Signature::Ihdr => { if index >= 4 { match parse_ihdr(&src[index - 4..]) { Ok(ihdr) => { @@ -189,7 +185,7 @@ pub fn find_compressable_stream( } } - Signature::IDAT => { + Signature::Idat => { if index >= 4 { // idat has the length first, then the "IDAT", so we need to look back 4 bytes // if we find and IDAT @@ -204,14 +200,14 @@ pub fn find_compressable_stream( if length > MIN_BLOCKSIZE { return FindStreamResult::Found( real_start..real_start + idat_contents.total_chunk_length, - FoundStream { + Box::new(FoundStream { chunk_type: FoundStreamType::IDATDeflate( res.parameters.unwrap(), idat_contents, state.detach_plain_text(), ), corrections: res.corrections, - }, + }), ); } else { // if we couldn't successfully decompress the IDAT, skip the IDAT @@ -230,7 +226,7 @@ pub fn find_compressable_stream( } } } - Signature::JPEG => { + Signature::Jpeg => { let mut output = Vec::new(); // only required feature is that we can stop reading at the EOI marker @@ -271,10 +267,10 @@ pub fn find_compressable_stream( // successfully encoded the JPEG stream, return the found stream return FindStreamResult::Found( index..index + input.position() as usize, - FoundStream { + Box::new(FoundStream { chunk_type: FoundStreamType::JPEGLepton(output), corrections: Vec::new(), - }, + }), ); } Err(e) => { @@ -419,13 +415,14 @@ fn find_streams(f: &[u8], chunk_size_limit: usize) -> Vec<(Range, ChunkTy let mut offset: usize = 0; let maxlen = f.len(); let mut locations_found = Vec::new(); - while let FindStreamResult::Found(loc, res) = find_compressable_stream( + while let FindStreamResult::Found(loc, res_box) = find_compressable_stream( &f[offset..maxlen.min(offset.saturating_add(chunk_size_limit))], &mut None, true, &PreflateContainerConfig::default(), ) { let r = offset + loc.start..offset + loc.end; + let res = *res_box; match res.chunk_type { FoundStreamType::DeflateStream(_, mut state) => { diff --git a/container/src/utils.rs b/container/src/utils.rs index 8d345f5..7ec4f42 100644 --- a/container/src/utils.rs +++ b/container/src/utils.rs @@ -119,7 +119,7 @@ pub fn process_limited_buffer( ) -> Result<(bool, usize)> { // first write any extra data we have pending from last time let mut amount_written = 0; - while amount_written < output_buffer.len() && output_extra.len() > 0 { + while amount_written < output_buffer.len() && !output_extra.is_empty() { amount_written += output_extra .read(&mut output_buffer[amount_written..]) .unwrap(); @@ -133,7 +133,7 @@ pub fn process_limited_buffer( }; process.process_buffer(input, input_complete, &mut w)?; - Ok((input_complete && w.extra_queue.len() == 0, w.amount_written)) + Ok((input_complete && w.extra_queue.is_empty(), w.amount_written)) } #[test] diff --git a/dll/src/unmanaged_api.rs b/dll/src/unmanaged_api.rs index 4d117c7..1073d10 100644 --- a/dll/src/unmanaged_api.rs +++ b/dll/src/unmanaged_api.rs @@ -1,8 +1,10 @@ use std::{ collections::VecDeque, panic::{AssertUnwindSafe, catch_unwind}, - ptr::{null, null_mut}, + ptr::null_mut, }; +#[cfg(test)] +use std::ptr::null; use preflate_container::{ PreflateContainerConfig, PreflateContainerProcessor, ProcessBuffer, RecreateContainerProcessor, @@ -15,7 +17,7 @@ fn catch_unwind_result( f: impl FnOnce() -> Result, ) -> Result { match catch_unwind(AssertUnwindSafe(f)) { - Ok(r) => r.map_err(|e| e.into()), + Ok(r) => r, Err(err) => { if let Some(message) = err.downcast_ref::<&str>() { Err(PreflateError::new(ExitCode::AssertionFailure, *message)) @@ -36,7 +38,7 @@ fn catch_unwind_result( /// copies a string into a limited length zero terminated utf8 buffer fn copy_cstring_utf8_to_buffer(str: &str, target_error_string: &mut [u8]) { - if target_error_string.len() == 0 { + if target_error_string.is_empty() { return; } @@ -76,6 +78,9 @@ fn test_copy_cstring_utf8_to_buffer() { /// can compare the preflate compression + zstd to just plain zstd compression) /// bit 6: if 1, skip verify after compress. This is useful if caller does a separate verify step after to save CPU time. /// *If this is set, the caller must verify the data after decompressing it as in some cases it may be not decompress successfully.* +/// +/// # Safety +/// Returns a raw pointer that must be freed with `free_compression_context`. #[unsafe(no_mangle)] pub unsafe extern "C" fn create_compression_context(flags: u32) -> *mut std::ffi::c_void { match catch_unwind_result(|| { @@ -100,6 +105,9 @@ pub unsafe extern "C" fn create_compression_context(flags: u32) -> *mut std::ffi } /// Frees the compression context +/// +/// # Safety +/// `context` must be a valid pointer returned by `create_compression_context`. #[unsafe(no_mangle)] pub unsafe extern "C" fn free_compression_context(context: *mut std::ffi::c_void) { unsafe { @@ -116,6 +124,10 @@ pub unsafe extern "C" fn free_compression_context(context: *mut std::ffi::c_void /// /// Returns 0 if more data is needed or if there is more data available, or 1 if done successfully. /// Returns < 0 if there is an error (negative value is the error code) +/// +/// # Safety +/// All pointer arguments must be valid for their specified lengths. `context` must be a valid +/// pointer returned by `create_compression_context`. #[unsafe(no_mangle)] pub unsafe extern "C" fn compress_buffer( context: *mut std::ffi::c_void, @@ -132,12 +144,12 @@ pub unsafe extern "C" fn compress_buffer( match catch_unwind_result(|| { let context = CompressionContext::from_pointer(context); - let input = if input_buffer == null() { + let input = if input_buffer.is_null() { &[] } else { std::slice::from_raw_parts(input_buffer, input_buffer_size as usize) }; - let output = if output_buffer == null_mut() { + let output = if output_buffer.is_null() { &mut [] } else { std::slice::from_raw_parts_mut(output_buffer, output_buffer_size as usize) @@ -156,7 +168,7 @@ pub unsafe extern "C" fn compress_buffer( }) { Ok(done) => done as i32, Err(e) => { - if error_string != null_mut() { + if !error_string.is_null() { copy_cstring_utf8_to_buffer( e.message(), std::slice::from_raw_parts_mut( @@ -172,6 +184,10 @@ pub unsafe extern "C" fn compress_buffer( } /// returns the compression statistics associated with the compression context +/// +/// # Safety +/// `context` must be a valid pointer returned by `create_compression_context`. All output +/// pointer arguments must be valid writable locations. #[unsafe(no_mangle)] pub unsafe extern "C" fn get_compression_stats( context: *mut std::ffi::c_void, @@ -264,6 +280,9 @@ impl DecompressionContext { } /// Allocates new decompression context, must be freed with free_decompression_context +/// +/// # Safety +/// Returns a raw pointer that must be freed with `free_decompression_context`. #[unsafe(no_mangle)] pub unsafe extern "C" fn create_decompression_context( _flags: u32, @@ -282,6 +301,9 @@ pub unsafe extern "C" fn create_decompression_context( } /// Frees the decompression context +/// +/// # Safety +/// `context` must be a valid pointer returned by `create_decompression_context`. #[unsafe(no_mangle)] pub unsafe extern "C" fn free_decompression_context(context: *mut std::ffi::c_void) { unsafe { @@ -298,6 +320,10 @@ pub unsafe extern "C" fn free_decompression_context(context: *mut std::ffi::c_vo /// /// Returns 0 if more data is needed or if there is more data available, or 1 if done successfully. /// Returns < 0 if there is an error (negative value is the error code) +/// +/// # Safety +/// All pointer arguments must be valid for their specified lengths. `context` must be a valid +/// pointer returned by `create_decompression_context`. #[unsafe(no_mangle)] pub unsafe extern "C" fn decompress_buffer( context: *mut std::ffi::c_void, @@ -314,12 +340,12 @@ pub unsafe extern "C" fn decompress_buffer( match catch_unwind_result(|| { let context = DecompressionContext::from_pointer(context); - let input = if input_buffer == null() { + let input = if input_buffer.is_null() { &[] } else { std::slice::from_raw_parts(input_buffer, input_buffer_size as usize) }; - let output = if output_buffer == null_mut() { + let output = if output_buffer.is_null() { &mut [] } else { std::slice::from_raw_parts_mut(output_buffer, output_buffer_size as usize) diff --git a/preflate/src/cabac_codec.rs b/preflate/src/cabac_codec.rs index b4a87f7..b651620 100644 --- a/preflate/src/cabac_codec.rs +++ b/preflate/src/cabac_codec.rs @@ -221,8 +221,8 @@ impl, CTX: Default> PredictionDecoderCabac { pub fn new(mut reader: R) -> Self { let mut actions_seen = [false; CodecCorrection::MAX as usize]; let mut actions_seen_ctx = CTX::default(); - for i in 0..actions_seen.len() { - actions_seen[i] = reader.get(&mut actions_seen_ctx).unwrap(); + for item in &mut actions_seen { + *item = reader.get(&mut actions_seen_ctx).unwrap(); } Self { @@ -247,7 +247,7 @@ impl, CTX: Default> PredictionDecoderCabac { ) + 1; self.default_actions[c] = value - 1; - return Err(0); + Err(0) } else { let value = PredictionCabacContext::read_exp_value( &mut self.context.correction_ctx[c], @@ -255,7 +255,7 @@ impl, CTX: Default> PredictionDecoderCabac { &mut self.reader, ) + 1; - return Err(value); + Err(value) } } } @@ -279,7 +279,7 @@ impl, CTX: Default> PredictionDecoder for PredictionDecoderC match self.decode_correction_slow(c) { Ok(value) => value, - Err(value) => return value, + Err(value) => value, } } } diff --git a/preflate/src/deflate/bit_reader.rs b/preflate/src/deflate/bit_reader.rs index e88525e..3aa092c 100644 --- a/preflate/src/deflate/bit_reader.rs +++ b/preflate/src/deflate/bit_reader.rs @@ -76,7 +76,7 @@ impl BitReader { self.read_ahead -= 1; } - self.bits = self.bits & ((1 << self.bits_left) - 1); + self.bits &= (1 << self.bits_left) - 1; if self.read_ahead > 0 { reader.consume(self.read_ahead as usize); diff --git a/preflate/src/deflate/deflate_constants.rs b/preflate/src/deflate/deflate_constants.rs index 3a23654..90d1e0f 100644 --- a/preflate/src/deflate/deflate_constants.rs +++ b/preflate/src/deflate/deflate_constants.rs @@ -102,7 +102,6 @@ pub fn quantize_distance(dist: u32) -> DistCode { } else { 256 + ((dist - 1) >> 7) } as usize] - .into() } pub fn quantize_length(len: u32) -> LengthCode { LENGTH_CODE_TABLE[len as usize - MIN_MATCH as usize] diff --git a/preflate/src/deflate/deflate_reader.rs b/preflate/src/deflate/deflate_reader.rs index cf1dda0..f513b1d 100644 --- a/preflate/src/deflate/deflate_reader.rs +++ b/preflate/src/deflate/deflate_reader.rs @@ -92,7 +92,7 @@ impl DeflateParser { // our first checkpoint is right at the beginning so that if we get to the // end of the stream before seeing a whole block, we just revert back to // the beginning to try again with more data. - let mut checkpoint = self.checkpoint(&mut cursor); + let mut checkpoint = self.checkpoint(cursor); let bits_left = self.bit_reader.bits_left(); if bits_left > 0 { @@ -103,38 +103,35 @@ impl DeflateParser { self.bit_reader.get(8 - bits_left, cursor)?; } - match self.read_blocks_internal(&mut cursor, &mut blocks, &mut checkpoint) { - Err(e) => { - // reset back to known good checkpoint before returning the error. - // this allows callers to try again once they have more data - self.bit_reader = checkpoint.bit_reader; - self.plain_text.truncate(checkpoint.plain_text); - - // if nothing was successfully read or we didn't - // get the out-of-data error, then just exit - // if we get a plain-text too big error, also checkpoint back - // to how far we got and the next part of the plaintext will be put in the next chunk - if checkpoint.position == 0 - || (e.exit_code() != ExitCode::ShortRead - && e.exit_code() != ExitCode::PlainTextLimit) - { - return Err(e); - } - - // if we had bits left to read, then we didn't compress the entire - // block, and save the bits for later - let compressed_size = if (self.bit_reader.bits_left() & 0x7) > 0 { - (checkpoint.position - 1) as usize - } else { - checkpoint.position as usize - }; - - return Ok(DeflateContents { - compressed_size, - blocks, - }); + if let Err(e) = self.read_blocks_internal(cursor, &mut blocks, &mut checkpoint) { + // reset back to known good checkpoint before returning the error. + // this allows callers to try again once they have more data + self.bit_reader = checkpoint.bit_reader; + self.plain_text.truncate(checkpoint.plain_text); + + // if nothing was successfully read or we didn't + // get the out-of-data error, then just exit + // if we get a plain-text too big error, also checkpoint back + // to how far we got and the next part of the plaintext will be put in the next chunk + if checkpoint.position == 0 + || (e.exit_code() != ExitCode::ShortRead + && e.exit_code() != ExitCode::PlainTextLimit) + { + return Err(e); } - Ok(()) => {} + + // if we had bits left to read, then we didn't compress the entire + // block, and save the bits for later + let compressed_size = if (self.bit_reader.bits_left() & 0x7) > 0 { + (checkpoint.position - 1) as usize + } else { + checkpoint.position as usize + }; + + return Ok(DeflateContents { + compressed_size, + blocks, + }); } self.bit_reader.undo_read_ahead(&mut cursor); diff --git a/preflate/src/deflate/deflate_token.rs b/preflate/src/deflate/deflate_token.rs index a725369..54b5531 100644 --- a/preflate/src/deflate/deflate_token.rs +++ b/preflate/src/deflate/deflate_token.rs @@ -69,18 +69,15 @@ pub const BT_DYNAMICHUFF: u32 = 0; pub const BT_STATICHUFF: u32 = 2; #[derive(Debug, PartialEq)] +#[derive(Default)] pub enum DeflateHuffmanType { + #[default] Static, Dynamic { huffman_encoding: HuffmanOriginalEncoding, }, } -impl Default for DeflateHuffmanType { - fn default() -> Self { - DeflateHuffmanType::Static - } -} #[derive(PartialEq)] pub enum DeflateTokenBlockType { @@ -99,7 +96,7 @@ impl std::fmt::Debug for DeflateTokenBlockType { match self { DeflateTokenBlockType::Huffman { tokens, - huffman_type: DeflateHuffmanType::Static { .. }, + huffman_type: DeflateHuffmanType::Static, } => { write!(f, "StaticHuffman {{ tokens: len={} }}", tokens.len(),) } diff --git a/preflate/src/deflate/deflate_writer.rs b/preflate/src/deflate/deflate_writer.rs index 3ea8aa4..c83c821 100644 --- a/preflate/src/deflate/deflate_writer.rs +++ b/preflate/src/deflate/deflate_writer.rs @@ -65,7 +65,7 @@ impl DeflateWriter { self.output .extend_from_slice(&(!uncompressed.len() as u16).to_le_bytes()); - self.output.extend_from_slice(&uncompressed); + self.output.extend_from_slice(uncompressed); } DeflateTokenBlockType::Huffman { tokens, @@ -86,7 +86,7 @@ impl DeflateWriter { let huffman_writer = HuffmanWriter::start_dynamic_huffman_table( &mut self.bitwriter, - &huffman_encoding, + huffman_encoding, &mut self.output, )?; diff --git a/preflate/src/deflate/huffman_calc.rs b/preflate/src/deflate/huffman_calc.rs index bbd96ff..bead6ca 100644 --- a/preflate/src/deflate/huffman_calc.rs +++ b/preflate/src/deflate/huffman_calc.rs @@ -40,10 +40,10 @@ mod calc_minzoxide { let mut symbols0 = Vec::new(); let mut max_used = 0; - for i in 0..sym_count.len() { - if sym_count[i] != 0 { + for (i, &count) in sym_count.iter().enumerate() { + if count != 0 { symbols0.push(SymFreq { - key: sym_count[i], + key: count, sym_index: i as u16, }); max_used = i + 1; @@ -279,7 +279,7 @@ mod calc_zlib { /// Restore the heap property by moving down the tree starting at node k. /// Exchange a node with the smallest of its two sons if necessary. /// Stop when the heap property is re-established (each father smaller than its two sons). - fn pqdownheap(heap: &mut Vec, mut root: usize) { + fn pqdownheap(heap: &mut [HuffTreeNode], mut root: usize) { /// Compares two subtrees using the tree depth as a tie-breaker when frequencies are equal. fn smaller(n: &HuffTreeNode, m: &HuffTreeNode) -> bool { n.freq < m.freq || (n.freq == m.freq && n.depth <= m.depth) diff --git a/preflate/src/deflate/huffman_encoding.rs b/preflate/src/deflate/huffman_encoding.rs index 8edb0eb..ee03c2d 100644 --- a/preflate/src/deflate/huffman_encoding.rs +++ b/preflate/src/deflate/huffman_encoding.rs @@ -90,8 +90,8 @@ fn is_valid_huffman_code_lengths(code_lengths: &[u8]) -> bool { // have exactly two children. This means that the number of internal // nodes doubles each time we go down one level in the tree. let mut internal_nodes = 2; - for i in 1..length_count.len() { - internal_nodes -= length_count[i]; + for &count in length_count.iter().skip(1) { + internal_nodes -= count; if internal_nodes < 0 { return false; } @@ -137,8 +137,8 @@ fn calculate_huffman_code_tree(code_lengths: &[u8]) -> Result { for c_bits_cur in (1..=c_bits_largest).rev() { let i_huff_nodes_start = i_huff_nodes; // Create parent nodes for all leaf codes at current bit length - for j in 0..code_lengths.len() { - if code_lengths[j] == c_bits_cur { + for (j, &cl) in code_lengths.iter().enumerate() { + if cl == c_bits_cur { tree[i_huff_nodes as usize] = !(j as u16); // Leaf nodes links store the actual literal character negative biased by -1 i_huff_nodes += 1; } @@ -155,7 +155,7 @@ fn calculate_huffman_code_tree(code_lengths: &[u8]) -> Result { // build a fast decoder that lets us decode the entire symbol given a byte of input let mut fast_decode = [(0u8, 0u16); 256]; - for i in 0..256 { + for (i, entry) in fast_decode.iter_mut().enumerate() { let mut i_node_cur = tree.len() - 2; // Start at the root of the Huffman tree let mut v = i; @@ -166,7 +166,7 @@ fn calculate_huffman_code_tree(code_lengths: &[u8]) -> Result { // High bit indicates a leaf node, return alphabet char for this leaf if (next & 0x8000) != 0 || num_bits == 8 { - fast_decode[i] = (num_bits, next); + *entry = (num_bits, next); break; } @@ -418,12 +418,8 @@ impl HuffmanOriginalEncoding { bitwriter.write(self.num_dist as u32 - 1, 5, output_buffer); bitwriter.write(self.num_code_lengths as u32 - 4, 4, output_buffer); - for i in 0..self.num_code_lengths { - bitwriter.write( - self.code_lengths[TREE_CODE_ORDER_TABLE[i]].into(), - 3, - output_buffer, - ); + for &order in TREE_CODE_ORDER_TABLE.iter().take(self.num_code_lengths) { + bitwriter.write(self.code_lengths[order].into(), 3, output_buffer); } let codes = calc_huffman_codes(&self.code_lengths)?; @@ -495,9 +491,7 @@ impl HuffmanOriginalEncoding { } } TreeCodeType::ZeroShort | TreeCodeType::ZeroLong => { - for _ in 0..length { - lengths.push(0); - } + lengths.extend(std::iter::repeat_n(0, length as usize)); } } } @@ -606,9 +600,7 @@ impl HuffmanReader { fn copy_to_array(src: &[T]) -> [T; N] { let mut dst = [T::default(); N]; - for i in 0..src.len().min(N) { - dst[i] = src[i]; - } + dst[..src.len().min(N)].copy_from_slice(&src[..src.len().min(N)]); dst } diff --git a/preflate/src/estimator/add_policy_estimator.rs b/preflate/src/estimator/add_policy_estimator.rs index 4f63f06..d8ba049 100644 --- a/preflate/src/estimator/add_policy_estimator.rs +++ b/preflate/src/estimator/add_policy_estimator.rs @@ -139,9 +139,7 @@ pub(super) fn estimate_add_policy(token_blocks: &[DeflateTokenBlock]) -> Diction let mut min_len = u32::MAX; - for i in 0..token_blocks.len() { - let token_block = &token_blocks[i]; - + for token_block in token_blocks { match &token_block.block_type { DeflateTokenBlockType::Stored { uncompressed, .. } => { // we assume for stored blocks everything was added to the dictionary diff --git a/preflate/src/estimator/complevel_estimator.rs b/preflate/src/estimator/complevel_estimator.rs index e31a3d5..a9ba666 100644 --- a/preflate/src/estimator/complevel_estimator.rs +++ b/preflate/src/estimator/complevel_estimator.rs @@ -40,7 +40,7 @@ pub fn estimate_preflate_comp_level( add_policy: DictionaryAddPolicy, ) -> Result { let hash_bits = mem_level + 7; - let mem_hash_shift = (hash_bits + 2) / 3; + let mem_hash_shift = hash_bits.div_ceil(3); let mem_hash_mask = ((1u32 << hash_bits) - 1) as u16; let wsize = 1 << wbits; diff --git a/preflate/src/estimator/depth_estimator.rs b/preflate/src/estimator/depth_estimator.rs index 467ffbc..984d379 100644 --- a/preflate/src/estimator/depth_estimator.rs +++ b/preflate/src/estimator/depth_estimator.rs @@ -147,7 +147,7 @@ impl HashTableDepthEstimatorImpl { fn internal_update_hash(&mut self, chars: &[u8], pos: u32, length: u32) { debug_assert!(length as usize <= chars.len()); - if length as usize + H::NUM_HASH_BYTES - 1 >= chars.len() { + if length as usize + H::NUM_HASH_BYTES > chars.len() { // reached on of the stream so there will be no more matches return; } @@ -247,7 +247,7 @@ const LIB_DEFLATE3_HASH: LibdeflateHash3Secondary = LibdeflateHash3Secondary {}; impl HashTableDepthEstimatorLibdeflate { fn internal_update_hash3(&mut self, chars: &[u8], pos: u32, length: u32) { debug_assert!(length as usize <= chars.len()); - if length as usize + 3 - 1 >= chars.len() { + if length as usize + 3 > chars.len() { // reached on of the stream so there will be no more matches return; } @@ -348,7 +348,7 @@ fn update_candidate_hashes( input: &mut PreflateInput, ) { for i in candidates { - i.update_hash(add_policy, &input, length); + i.update_hash(add_policy, input, length); } input.advance(length); @@ -363,9 +363,9 @@ pub fn run_depth_candidates( plain_text: &PlainText, candidates: &mut Vec>, ) { - let mut input = PreflateInput::new(&plain_text); + let mut input = PreflateInput::new(plain_text); - for (_i, b) in deflate.blocks.iter().enumerate() { + for b in deflate.blocks.iter() { match &b.block_type { DeflateTokenBlockType::Stored { uncompressed, .. } => { for _i in 0..uncompressed.len() { @@ -373,7 +373,7 @@ pub fn run_depth_candidates( } } DeflateTokenBlockType::Huffman { tokens, .. } => { - for (_j, t) in tokens.iter().enumerate() { + for t in tokens.iter() { match t { DeflateToken::Literal(_) => { update_candidate_hashes(1, candidates, add_policy, &mut input); diff --git a/preflate/src/estimator/preflate_parameter_estimator.rs b/preflate/src/estimator/preflate_parameter_estimator.rs index cd56d53..3798a45 100644 --- a/preflate/src/estimator/preflate_parameter_estimator.rs +++ b/preflate/src/estimator/preflate_parameter_estimator.rs @@ -120,7 +120,7 @@ pub fn estimate_preflate_parameters( matches_to_start_detected: info.matches_to_start_detected, strategy: estimate_preflate_strategy(&info), nice_length: cl.nice_length, - add_policy: add_policy, + add_policy, max_token_count, zlib_compatible, max_dist_3_matches: info.max_dist_3_matches, @@ -148,7 +148,7 @@ fn estimate_preflate_mem_level(max_block_size_: u32) -> u32 { mbits += 1; max_block_size >>= 1; } - mbits = std::cmp::min(std::cmp::max(mbits, 7), 15); + mbits = mbits.clamp(7, 15); mbits - 6 } @@ -156,7 +156,7 @@ fn estimate_preflate_window_bits(max_dist_: u32) -> u32 { let mut max_dist = max_dist_; max_dist += deflate_constants::MIN_LOOKAHEAD; let wbits = bit_length(max_dist - 1); - std::cmp::min(std::cmp::max(wbits, 9), 15) + wbits.clamp(9, 15) } fn estimate_preflate_strategy(info: &PreflateStreamInfo) -> PreflateStrategy { diff --git a/preflate/src/estimator/preflate_stream_info.rs b/preflate/src/estimator/preflate_stream_info.rs index 38ead82..635dc75 100644 --- a/preflate/src/estimator/preflate_stream_info.rs +++ b/preflate/src/estimator/preflate_stream_info.rs @@ -30,8 +30,8 @@ fn process_tokens(tokens: &[DeflateToken], result: &mut PreflateStreamInfo, posi let mut block_max_dist = 0; let mut block_min_len = u32::MAX; - for j in 0..tokens.len() { - match &tokens[j] { + for token in tokens { + match token { DeflateToken::Literal(_) => { result.literal_count += 1; *position += 1; @@ -80,8 +80,8 @@ pub(crate) fn extract_preflate_info(blocks: &[DeflateTokenBlock]) -> PreflateStr }; let mut position = 0; - for i in 0..blocks.len() { - match &blocks[i].block_type { + for block in blocks { + match &block.block_type { DeflateTokenBlockType::Stored { uncompressed, .. } => { result.count_stored_blocks += 1; position += uncompressed.len() as u32; @@ -91,10 +91,10 @@ pub(crate) fn extract_preflate_info(blocks: &[DeflateTokenBlock]) -> PreflateStr huffman_type, .. } => { - if let DeflateHuffmanType::Static { .. } = huffman_type { + if let DeflateHuffmanType::Static = huffman_type { result.count_static_huff_tree_blocks += 1; } - process_tokens(&tokens, &mut result, &mut position); + process_tokens(tokens, &mut result, &mut position); } } } diff --git a/preflate/src/hash_chain.rs b/preflate/src/hash_chain.rs index e6c5bbc..76cd75a 100644 --- a/preflate/src/hash_chain.rs +++ b/preflate/src/hash_chain.rs @@ -86,7 +86,7 @@ impl HashTable { ) { debug_assert!(length as usize <= chars.len()); - if length as usize + H::NUM_HASH_BYTES - 1 >= chars.len() { + if length as usize + H::NUM_HASH_BYTES > chars.len() { // if we reached the end of the buffer, hash only while we have characters left length = chars.len().saturating_sub(H::NUM_HASH_BYTES - 1) as u32; } @@ -115,7 +115,7 @@ impl HashTable { *x = x.reshift(DELTA as u16); } - assert!((DELTA % 16) == 0, "assuming we can do blocks of 16"); + assert!(DELTA.is_multiple_of(16), "assuming we can do blocks of 16"); for i in DELTA / 16..65536 / 16 { let (a, b) = self.prev.split_at_mut(i * 16); @@ -163,7 +163,7 @@ impl HashChainDefault { HashChainDefault { total_shift: -8, hash_table: HashTable::default_boxed(), - hash: hash, + hash, } } @@ -216,12 +216,11 @@ impl HashChain for HashChainDefault { let mut cur_pos = self.hash_table.get_head(curr_hash); std::iter::from_fn(move || { - if OFFSET != 0 { - if let Some(d) = first_match { + if OFFSET != 0 + && let Some(d) = first_match { first_match = None; return Some(d); } - } if cur_pos.is_valid() { let d = ref_pos.dist(cur_pos); cur_pos = self.hash_table.prev[cur_pos.to_index()]; diff --git a/preflate/src/hash_chain_holder.rs b/preflate/src/hash_chain_holder.rs index 7d035f0..ad06cbe 100644 --- a/preflate/src/hash_chain_holder.rs +++ b/preflate/src/hash_chain_holder.rs @@ -395,6 +395,7 @@ impl HashChainHolderImpl { /// searches for a match that is at least 3 bytes long #[inline] +#[allow(clippy::too_many_arguments)] fn match_less3( input: &PreflateInput<'_>, max_len: u32, @@ -462,6 +463,7 @@ fn match_less3( /// Once we know that we have a least a 3 byte match, we can be faster by comparing 4 bytes at a time #[inline] +#[allow(clippy::too_many_arguments)] fn match_4( input: &PreflateInput<'_>, max_len: u32, @@ -469,7 +471,7 @@ fn match_4( nice_length: u32, mut max_chain: u32, mut best_len: u32, - mut iter: impl Iterator, + iter: impl Iterator, best: &mut MatchResult, ) { let input_chars = input.cur_chars(OFFSET as i32); @@ -477,7 +479,7 @@ fn match_4( // look at last 3 characters of best length so far + 1 because we want to improve the match let mut c0 = read_u32_le(input_chars, (best_len - 3) as usize); - while let Some(dist) = iter.next() { + for dist in iter { if dist > max_dist { break; } @@ -535,7 +537,7 @@ fn prefix_compare_fast(s1: &[u8], s2: &[u8]) -> u32 { if s1[257] != s2[257] { return 257; } - return 258; + 258 } #[inline(never)] @@ -574,5 +576,5 @@ fn calc_diff(diff: u64) -> u32 { if diff != 0 { return diff.trailing_zeros() / 8; } - return 8; + 8 } diff --git a/preflate/src/preflate_error.rs b/preflate/src/preflate_error.rs index dc2d674..575bfa8 100644 --- a/preflate/src/preflate_error.rs +++ b/preflate/src/preflate_error.rs @@ -139,7 +139,7 @@ impl PreflateError { pub fn err_exit_code(error_code: ExitCode, message: impl AsRef) -> Result { let mut e = PreflateError::new(error_code, message.as_ref()); e.add_context(); - return Err(e); + Err(e) } pub trait AddContext { @@ -200,7 +200,7 @@ impl From for PreflateError { fn from(e: std::io::Error) -> Self { match e.downcast::() { Ok(le) => { - return le; + le } Err(e) => { let mut e = PreflateError::new(get_io_error_exit_code(&e), e.to_string().as_str()); @@ -214,7 +214,7 @@ impl From for PreflateError { /// translates PreflateError into std::io::Error, which involves putting into a Box and using Other impl From for std::io::Error { fn from(e: PreflateError) -> Self { - return std::io::Error::new(std::io::ErrorKind::Other, e); + std::io::Error::other(e) } } diff --git a/preflate/src/preflate_input.rs b/preflate/src/preflate_input.rs index 2a346a8..a786356 100644 --- a/preflate/src/preflate_input.rs +++ b/preflate/src/preflate_input.rs @@ -44,6 +44,12 @@ impl Clone for PlainText { } } +impl Default for PlainText { + fn default() -> Self { + Self::new() + } +} + impl PlainText { pub fn new() -> Self { Self { @@ -77,6 +83,10 @@ impl PlainText { self.data.len() - (self.prefix_length as usize) } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// the total length of the data from the beginning pub fn total_length(&self) -> u32 { self.pos_offset as u32 + self.len() as u32 diff --git a/preflate/src/statistical_codec.rs b/preflate/src/statistical_codec.rs index c2c7613..75f4166 100644 --- a/preflate/src/statistical_codec.rs +++ b/preflate/src/statistical_codec.rs @@ -225,7 +225,7 @@ impl PredictionDecoder for VerifyPredictionDecoder { match x { CodecAction::Correction(c, value) => { assert_eq!(correction, c); - return value; + value } CodecAction::VerifyState(s, _h) => { panic!("found VerifyState {}, expected {:?}", s, correction); diff --git a/preflate/src/stream_processor.rs b/preflate/src/stream_processor.rs index 717ca49..c70ea8a 100644 --- a/preflate/src/stream_processor.rs +++ b/preflate/src/stream_processor.rs @@ -93,7 +93,7 @@ impl PreflateStreamProcessor { } pub fn plain_text(&self) -> &PlainText { - &self.parser.plain_text() + self.parser.plain_text() } pub fn shrink_to_dictionary(&mut self) { @@ -114,7 +114,7 @@ impl PreflateStreamProcessor { PredictionEncoderCabac::new(VP8Writer::new(&mut cabac_encoded).unwrap()); if let Some(predictor) = &mut self.predictor { - let mut input = PreflateInput::new(&self.parser.plain_text()); + let mut input = PreflateInput::new(self.parser.plain_text()); // we are missing the last couple hashes in the dictionary since we didn't // have the full plaintext yet. @@ -158,7 +158,7 @@ impl PreflateStreamProcessor { }) } else { let params = - estimate_preflate_parameters(&contents, &self.parser.plain_text()).context()?; + estimate_preflate_parameters(&contents, self.parser.plain_text()).context()?; if params.max_chain > self.max_chain_length { return Err(PreflateError::new( @@ -170,7 +170,7 @@ impl PreflateStreamProcessor { )); } - let mut input = PreflateInput::new(&self.parser.plain_text()); + let mut input = PreflateInput::new(self.parser.plain_text()); let mut token_predictor = TokenPredictor::new(¶ms); @@ -246,6 +246,12 @@ pub struct RecreateStreamProcessor { plain_text: PlainText, } +impl Default for RecreateStreamProcessor { + fn default() -> Self { + Self::new() + } +} + impl RecreateStreamProcessor { pub fn new() -> Self { Self { @@ -267,7 +273,7 @@ impl RecreateStreamProcessor { break; } - self.plain_text.append(&buf); + self.plain_text.append(buf); plain_text.consume(buf_len); } diff --git a/preflate/src/token_predictor.rs b/preflate/src/token_predictor.rs index 5128b28..6036934 100644 --- a/preflate/src/token_predictor.rs +++ b/preflate/src/token_predictor.rs @@ -58,7 +58,10 @@ impl TokenPredictor { } pub fn checksum(&self) -> DebugHash { - assert!(VERIFY); + #[allow(clippy::assertions_on_constants)] + { + assert!(VERIFY); + } let mut c = DebugHash::default(); self.state.checksum(&mut c); c @@ -92,10 +95,10 @@ impl TokenPredictor { codec.encode_verify_state("blocktypestart", 0); - let tokens; + let huffman_encoding; - match &block.block_type { + let tokens = match &block.block_type { DeflateTokenBlockType::Stored { uncompressed } => { codec.encode_correction_diff( CodecCorrection::BlockTypeCorrection, @@ -110,7 +113,7 @@ impl TokenPredictor { ); for _i in 0..uncompressed.len() { - self.state.update_hash(1, &input); + self.state.update_hash(1, input); input.advance(1); } @@ -131,7 +134,7 @@ impl TokenPredictor { .. } => { match huffman_type { - DeflateHuffmanType::Static { .. } => { + DeflateHuffmanType::Static => { codec.encode_correction_diff( CodecCorrection::BlockTypeCorrection, BT_STATICHUFF, @@ -152,9 +155,9 @@ impl TokenPredictor { } } - tokens = t + t } - } + }; // if the block ends at an unexpected point, or it contains more tokens // than expected, we will need to encode the block size @@ -173,9 +176,7 @@ impl TokenPredictor { let mut freq = TokenFrequency::default(); - for i in 0..tokens.len() { - let target_token = &tokens[i]; - + for (i, target_token) in tokens.iter().enumerate() { codec.encode_verify_state( "token", if VERIFY { @@ -338,7 +339,7 @@ impl TokenPredictor { for _i in 0..uncompressed_len { uncompressed.push(input.cur_char(0)); - self.state.update_hash(1, &input); + self.state.update_hash(1, input); input.advance(1); } @@ -494,7 +495,7 @@ impl TokenPredictor { // match is too small and far way to be worth encoding as a distance/length pair. if match_token.len() == 3 - && match_token.dist() > u32::from(self.params.max_dist_3_matches) + && match_token.dist() > self.params.max_dist_3_matches { return DeflateToken::Literal(input.cur_char(0)); } @@ -505,8 +506,7 @@ impl TokenPredictor { good_length, max_lazy, } = self.params.matching_type - { - if match_token.len() < u32::from(max_lazy) + && match_token.len() < u32::from(max_lazy) && input.remaining() >= match_token.len() + 2 { let mut max_depth = self.params.max_chain; @@ -520,8 +520,8 @@ impl TokenPredictor { .state .match_token_1(match_token.len(), max_depth, input); - if let MatchResult::Success(m) = match_next { - if m.len() > match_token.len() { + if let MatchResult::Success(m) = match_next + && m.len() > match_token.len() { self.pending_reference = Some(m); if !self.params.zlib_compatible { @@ -529,9 +529,7 @@ impl TokenPredictor { } return DeflateToken::Literal(input.cur_char(0)); } - } } - } DeflateToken::Reference(match_token) } else { @@ -565,20 +563,18 @@ impl TokenPredictor { self.pending_reference = None; - if let MatchResult::Success(m) = match_token { - if m.len() >= MIN_MATCH { + if let MatchResult::Success(m) = match_token + && m.len() >= MIN_MATCH { return Ok(m); } - } // If we didn't find a match, try again with a larger chain let match_token = self.state.match_token_0(0, 4096, input); - if let MatchResult::Success(m) = match_token { - if m.len() >= MIN_MATCH { + if let MatchResult::Success(m) = match_token + && m.len() >= MIN_MATCH { return Ok(m); } - } err_exit_code( ExitCode::PredictionFailure, diff --git a/util/src/main.rs b/util/src/main.rs index 1a8ad90..ca1117f 100644 --- a/util/src/main.rs +++ b/util/src/main.rs @@ -121,9 +121,9 @@ fn main() { compress_start.elapsed() ); - totalseen += stats.deflate_compressed_size as u64; - totalbaseline += stats.zstd_baseline_size as u64; - totalzstd += stats.zstd_compressed_size as u64; + totalseen += stats.deflate_compressed_size; + totalbaseline += stats.zstd_baseline_size; + totalzstd += stats.zstd_compressed_size; println!( "total seen ratio {totalzstd}:{totalbaseline}:{totalseen} {:.1}",