diff --git a/.github/workflows/oxipng.yml b/.github/workflows/oxipng.yml index 8ba376ac..e653b658 100644 --- a/.github/workflows/oxipng.yml +++ b/.github/workflows/oxipng.yml @@ -161,7 +161,7 @@ jobs: - name: Install MSRV Rust toolchain uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: 1.74.0 + toolchain: 1.85.1 cache-bin: false cache-shared-key: cache diff --git a/Cargo.toml b/Cargo.toml index 387508b0..6f6d8826 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ categories = ["command-line-utilities", "compression"] description = "A lossless PNG compression optimizer" keywords = ["png", "image-compression", "optimization", "multi-threading", "lossless"] documentation = "https://docs.rs/oxipng" -edition = "2021" +edition = "2024" exclude = [ ".editorconfig", ".gitattributes", @@ -21,7 +21,7 @@ license = "MIT" name = "oxipng" repository = "https://github.com/oxipng/oxipng" version = "9.1.5" -rust-version = "1.74.0" +rust-version = "1.85.1" [badges] travis-ci = { repository = "oxipng/oxipng", branch = "master" } diff --git a/Dockerfile b/Dockerfile index c8e27bab..fc5a2fd2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # check=error=true FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx -FROM --platform=$BUILDPLATFORM rust:1.74-alpine AS base +FROM --platform=$BUILDPLATFORM rust:1.85.1-alpine AS base RUN apk update && \ apk add \ diff --git a/README.md b/README.md index 10b855ce..9c41e644 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ cargo build --release cp target/release/oxipng /usr/local/bin ``` -The current minimum supported Rust version is **1.74.0**. +The current minimum supported Rust version is **1.85.1**. Oxipng follows Semantic Versioning. diff --git a/benches/zopfli.rs b/benches/zopfli.rs index 912782fe..345a71ab 100644 --- a/benches/zopfli.rs +++ b/benches/zopfli.rs @@ -8,8 +8,7 @@ use std::{num::NonZeroU8, path::PathBuf}; use oxipng::{internal_tests::*, *}; use test::Bencher; -// SAFETY: trivially safe. Stopgap solution until const unwrap is stabilized. -const DEFAULT_ZOPFLI_ITERATIONS: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(15) }; +const DEFAULT_ZOPFLI_ITERATIONS: NonZeroU8 = NonZeroU8::new(15).unwrap(); #[bench] fn zopfli_16_bits_strategy_0(b: &mut Bencher) { diff --git a/src/apng.rs b/src/apng.rs index 8b99d0f1..b2817e1e 100644 --- a/src/apng.rs +++ b/src/apng.rs @@ -1,9 +1,9 @@ use std::io::Write; use crate::{ + PngResult, error::PngError, headers::{read_be_u16, read_be_u32}, - PngResult, }; #[derive(Debug, Clone)] diff --git a/src/atomicmin.rs b/src/atomicmin.rs index 57303e6d..e01163f4 100644 --- a/src/atomicmin.rs +++ b/src/atomicmin.rs @@ -15,11 +15,7 @@ impl AtomicMin { pub fn get(&self) -> Option { let val = self.val.load(SeqCst); - if val == usize::MAX { - None - } else { - Some(val) - } + if val == usize::MAX { None } else { Some(val) } } /// Try a new value, returning true if it is the new minimum diff --git a/src/cli.rs b/src/cli.rs index 2d6f729a..800da204 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use clap::{value_parser, Arg, ArgAction, Command}; +use clap::{Arg, ArgAction, Command, value_parser}; include!("display_chunks.rs"); diff --git a/src/evaluate.rs b/src/evaluate.rs index f15aaed9..af6c4070 100644 --- a/src/evaluate.rs +++ b/src/evaluate.rs @@ -4,12 +4,12 @@ #[cfg(not(feature = "parallel"))] use std::cell::RefCell; use std::sync::{ - atomic::{AtomicUsize, Ordering::*}, Arc, + atomic::{AtomicUsize, Ordering::*}, }; #[cfg(feature = "parallel")] -use crossbeam_channel::{unbounded, Receiver, Sender}; +use crossbeam_channel::{Receiver, Sender, unbounded}; use deflate::Deflaters; use indexmap::IndexSet; use log::trace; @@ -17,7 +17,7 @@ use rayon::prelude::*; #[cfg(not(feature = "parallel"))] use crate::rayon; -use crate::{atomicmin::AtomicMin, deflate, filters::RowFilter, png::PngImage, Deadline, PngError}; +use crate::{Deadline, PngError, atomicmin::AtomicMin, deflate, filters::RowFilter, png::PngImage}; pub(crate) struct Candidate { pub image: Arc, @@ -30,7 +30,7 @@ pub(crate) struct Candidate { } impl Candidate { - fn cmp_key(&self) -> impl Ord { + fn cmp_key(&self) -> impl Ord + use<> { ( self.estimated_output_size, self.image.data.len(), @@ -161,10 +161,7 @@ impl Evaluator { best_candidate_size.set_min(estimated_output_size); trace!( "Eval: {}-bit {:23} {:8} {} bytes", - image.ihdr.bit_depth, - description, - filter, - estimated_output_size + image.ihdr.bit_depth, description, filter, estimated_output_size ); #[cfg(feature = "parallel")] @@ -182,10 +179,7 @@ impl Evaluator { } else if let Err(PngError::DeflatedDataTooLong(size)) = idat_data { trace!( "Eval: {}-bit {:23} {:8} >{} bytes", - image.ihdr.bit_depth, - description, - filter, - size + image.ihdr.bit_depth, description, filter, size ); } }); diff --git a/src/headers.rs b/src/headers.rs index 21786d4d..db48f15b 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -3,12 +3,12 @@ use log::{debug, trace, warn}; use rgb::{RGB16, RGBA8}; use crate::{ + Deflaters, Options, PngResult, colors::{BitDepth, ColorType}, deflate::{crc32, inflate}, display_chunks::DISPLAY_CHUNKS, error::PngError, interlace::Interlacing, - Deflaters, Options, PngResult, }; #[derive(Debug, Clone)] diff --git a/src/interlace.rs b/src/interlace.rs index 07af3b1e..7b4f2f5e 100644 --- a/src/interlace.rs +++ b/src/interlace.rs @@ -2,7 +2,7 @@ use std::{fmt, fmt::Display}; use bitvec::prelude::*; -use crate::{headers::IhdrData, png::PngImage, PngError}; +use crate::{PngError, headers::IhdrData, png::PngImage}; /// Whether to enable progressive rendering. See [`Options`][crate::Options]) #[repr(u8)] diff --git a/src/lib.rs b/src/lib.rs index c3d6dba0..1af2e8e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,16 +27,16 @@ mod rayon; use std::{ fs::{File, Metadata}, - io::{stdin, stdout, BufWriter, Read, Write}, + io::{BufWriter, Read, Write, stdin, stdout}, path::Path, sync::{ - atomic::{AtomicBool, Ordering}, Arc, + atomic::{AtomicBool, Ordering}, }, time::{Duration, Instant}, }; -pub use indexmap::{indexset, IndexSet}; +pub use indexmap::{IndexSet, indexset}; use log::{debug, info, trace, warn}; use rayon::prelude::*; pub use rgb::{RGB16, RGBA8}; @@ -232,9 +232,9 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<( if is_fully_optimized(in_data.len(), optimized_output.len(), opts) { match (output, input) { - // if p is None, it also means same as the input path - (OutFile::Path { path, .. }, InFile::Path(ref input_path)) - if path.as_ref().map_or(true, |p| p == input_path) => + // If output path is None, it also means same as the input path + (OutFile::Path { path, .. }, InFile::Path(input_path)) + if path.as_ref().is_none_or(|p| p == input_path) => { info!("{input}: Could not optimize further, no change written"); return Ok(()); @@ -396,7 +396,9 @@ fn optimize_png( } if opts.interlace == Some(Interlacing::Adam7) && png.raw.ihdr.interlaced != Interlacing::Adam7 { - warn!("Interlacing was not enabled as it would result in a larger file. To override this, use `--force`."); + warn!( + "Interlacing was not enabled as it would result in a larger file. To override this, use `--force`." + ); } #[cfg(feature = "sanity-checks")] @@ -471,7 +473,7 @@ fn optimize_raw( }; if result.data_is_compressed - && max_size.map_or(true, |max_size| result.estimated_output_size < max_size) + && max_size.is_none_or(|max_size| result.estimated_output_size < max_size) { debug!("Found better result:"); debug!(" {}, f = {}", deflater, result.filter); diff --git a/src/main.rs b/src/main.rs index 52623a7d..12794f44 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ use std::{ use clap::ArgMatches; mod cli; use indexmap::IndexSet; -use log::{error, warn, Level, LevelFilter}; +use log::{Level, LevelFilter, error, warn}; use oxipng::{Deflaters, InFile, Options, OutFile, PngError, RowFilter, StripChunks}; use rayon::prelude::*; diff --git a/src/options.rs b/src/options.rs index b7ff717e..60353f82 100644 --- a/src/options.rs +++ b/src/options.rs @@ -4,7 +4,7 @@ use std::{ time::Duration, }; -use indexmap::{indexset, IndexSet}; +use indexmap::{IndexSet, indexset}; use log::warn; use crate::{deflate::Deflaters, filters::RowFilter, headers::StripChunks, interlace::Interlacing}; diff --git a/src/png/mod.rs b/src/png/mod.rs index a872107a..66ba002d 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -12,14 +12,14 @@ use rgb::ComponentSlice; use rustc_hash::FxHashMap; use crate::{ + Options, apng::*, colors::{BitDepth, ColorType}, deflate, error::PngError, filters::*, headers::*, - interlace::{deinterlace_image, interlace_image, Interlacing}, - Options, + interlace::{Interlacing, deinterlace_image, interlace_image}, }; pub(crate) mod scan_lines; diff --git a/src/reduction/color.rs b/src/reduction/color.rs index ddf40234..0d1dde81 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -1,7 +1,7 @@ use std::hash::{BuildHasherDefault, Hash}; use indexmap::IndexSet; -use rgb::{alt::Gray, ComponentMap, ComponentSlice, FromSlice, RGB, RGBA}; +use rgb::{ComponentMap, ComponentSlice, FromSlice, RGB, RGBA, alt::Gray}; use rustc_hash::FxHasher; use crate::{ diff --git a/src/reduction/mod.rs b/src/reduction/mod.rs index dc6202a1..132ae802 100644 --- a/src/reduction/mod.rs +++ b/src/reduction/mod.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::{evaluate::Evaluator, png::PngImage, ColorType, Deadline, Deflaters, Options}; +use crate::{ColorType, Deadline, Deflaters, Options, evaluate::Evaluator, png::PngImage}; pub mod alpha; use crate::alpha::*; @@ -183,7 +183,7 @@ pub(crate) fn perform_reductions( if (!cheap || reduced.is_none()) && !deadline.passed() { if let Some(indexed) = indexed.and_then(|png| reduced_bit_depth_8_or_less(&png)) { // Only evaluate this if it's different from the first result (which must be grayscale if it exists) - if reduced.as_ref().map_or(true, |r| r.data != indexed.data) { + if reduced.as_ref().is_none_or(|r| r.data != indexed.data) { eval.try_image(Arc::new(indexed)); evaluation_added = true; } diff --git a/src/reduction/palette.rs b/src/reduction/palette.rs index b694b228..0d07d986 100644 --- a/src/reduction/palette.rs +++ b/src/reduction/palette.rs @@ -2,10 +2,10 @@ use indexmap::IndexSet; use rgb::RGBA8; use crate::{ + Interlacing, colors::{BitDepth, ColorType}, headers::IhdrData, - png::{scan_lines::ScanLine, PngImage}, - Interlacing, + png::{PngImage, scan_lines::ScanLine}, }; /// Attempt to reduce the number of colors in the palette, returning the reduced image if successful diff --git a/tests/flags.rs b/tests/flags.rs index ed4770cf..1ecffe63 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -99,11 +99,11 @@ fn test_it_converts( fn verbose_mode() { use std::cell::RefCell; #[cfg(not(feature = "parallel"))] - use std::sync::mpsc::{channel as unbounded, Sender}; + use std::sync::mpsc::{Sender, channel as unbounded}; #[cfg(feature = "parallel")] - use crossbeam_channel::{unbounded, Sender}; - use log::{set_logger, set_max_level, Level, LevelFilter, Log, Metadata, Record}; + use crossbeam_channel::{Sender, unbounded}; + use log::{Level, LevelFilter, Log, Metadata, Record, set_logger, set_max_level}; // Rust runs tests in parallel by default. // We want to make sure that we verify only logs from our test.