Skip to content

Commit

Permalink
release: 3.1.7
Browse files Browse the repository at this point in the history
  • Loading branch information
joshstoik1 committed Sep 6, 2024
2 parents 16e8305 + e13d430 commit e26ee4f
Show file tree
Hide file tree
Showing 25 changed files with 602 additions and 259 deletions.
26 changes: 13 additions & 13 deletions CREDITS.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
# Project Dependencies
Package: flaca
Version: 3.1.6
Generated: 2024-08-13 18:34:14 UTC
Version: 3.1.7
Generated: 2024-09-06 03:07:10 UTC

| Package | Version | Author(s) | License |
| ---- | ---- | ---- | ---- |
| [ahash](https://github.com/tkaitchuck/ahash) | 0.8.11 | [Tom Kaitchuck](mailto:tom.kaitchuck@gmail.com) | Apache-2.0 or MIT |
| [argyle](https://github.com/Blobfolio/argyle) | 0.8.0 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [argyle](https://github.com/Blobfolio/argyle) | 0.8.1 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [bitvec](https://github.com/bitvecto-rs/bitvec) | 1.0.1 | | MIT |
| [bytecount](https://github.com/llogiq/bytecount) | 0.6.8 | [Andre Bogus](mailto:bogusandre@gmail.de) and [Joshua Landau](mailto:joshua@landau.ws) | Apache-2.0 or MIT |
| [bytemuck](https://github.com/Lokathor/bytemuck) | 1.16.3 | [Lokathor](mailto:zefria@gmail.com) | Apache-2.0, MIT, or Zlib |
| [bytemuck](https://github.com/Lokathor/bytemuck) | 1.18.0 | [Lokathor](mailto:zefria@gmail.com) | Apache-2.0, MIT, or Zlib |
| [cfg-if](https://github.com/alexcrichton/cfg-if) | 1.0.0 | [Alex Crichton](mailto:alex@alexcrichton.com) | Apache-2.0 or MIT |
| [crc32fast](https://github.com/srijs/rust-crc32fast) | 1.4.2 | [Sam Rijs](mailto:srijs@airpost.net) and [Alex Crichton](mailto:alex@alexcrichton.com) | Apache-2.0 or MIT |
| [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) | 0.5.13 | | Apache-2.0 or MIT |
| [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) | 0.8.20 | | Apache-2.0 or MIT |
| [ctrlc](https://github.com/Detegr/rust-ctrlc.git) | 3.4.5 | [Antti Keränen](mailto:detegr@gmail.com) | Apache-2.0 or MIT |
| [dactyl](https://github.com/Blobfolio/dactyl) | 0.7.2 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [dowser](https://github.com/Blobfolio/dowser) | 0.9.2 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [dactyl](https://github.com/Blobfolio/dactyl) | 0.7.3 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [dowser](https://github.com/Blobfolio/dowser) | 0.9.3 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [equivalent](https://github.com/cuviper/equivalent) | 1.0.1 | | Apache-2.0 or MIT |
| [fastrand](https://github.com/smol-rs/fastrand) | 2.1.0 | [Stjepan Glavina](mailto:stjepang@gmail.com) | Apache-2.0 or MIT |
| flapfli | 3.1.6 | [Josh Stoik](mailto:josh@blobfolio.com) | WTFPL |
| [fastrand](https://github.com/smol-rs/fastrand) | 2.1.1 | [Stjepan Glavina](mailto:stjepang@gmail.com) | Apache-2.0 or MIT |
| flapfli | 3.1.7 | [Josh Stoik](mailto:josh@blobfolio.com) | WTFPL |
| [funty](https://github.com/myrrlyn/funty) | 2.0.0 | [myrrlyn](mailto:self@myrrlyn.dev) | MIT |
| [fyi_msg](https://github.com/Blobfolio/fyi) | 0.13.6 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [fyi_msg](https://github.com/Blobfolio/fyi) | 0.14.0 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [hashbrown](https://github.com/rust-lang/hashbrown) | 0.14.5 | [Amanieu d'Antras](mailto:amanieu@gmail.com) | Apache-2.0 or MIT |
| [indexmap](https://github.com/indexmap-rs/indexmap) | 2.3.0 | | Apache-2.0 or MIT |
| [libc](https://github.com/rust-lang/libc) | 0.2.155 | The Rust Project Developers | Apache-2.0 or MIT |
| [indexmap](https://github.com/indexmap-rs/indexmap) | 2.5.0 | | Apache-2.0 or MIT |
| [libc](https://github.com/rust-lang/libc) | 0.2.158 | The Rust Project Developers | Apache-2.0 or MIT |
| [libdeflate-sys](https://github.com/adamkewley/libdeflater) | 1.21.0 | [Adam Kewley](mailto:contact@adamkewley.com) | Apache-2.0 |
| [libdeflater](https://github.com/adamkewley/libdeflater) | 1.21.0 | [Adam Kewley](mailto:contact@adamkewley.com) | Apache-2.0 |
| [log](https://github.com/rust-lang/log) | 0.4.22 | The Rust Project Developers | Apache-2.0 or MIT |
| [mozjpeg-sys](https://github.com/kornelski/mozjpeg-sys.git) | 2.2.1 | [Kornel](mailto:kornel@geekhood.net) | IJG AND Zlib AND BSD-3-Clause |
| [once_cell](https://github.com/matklad/once_cell) | 1.19.0 | [Aleksey Kladov](mailto:aleksey.kladov@gmail.com) | Apache-2.0 or MIT |
| [oxipng](https://github.com/shssoichiro/oxipng) | 9.1.2 | [Joshua Holmer](mailto:jholmer.in@gmail.com) | MIT |
| [radium](https://github.com/bitvecto-rs/radium) | 0.7.0 | [Nika Layzell](mailto:nika@thelayzells.com) and [myrrlyn](mailto:self@myrrlyn.dev) | MIT |
| [rgb](https://github.com/kornelski/rust-rgb) | 0.8.48 | [Kornel Lesiński](mailto:kornel@geekhood.net) and [James Forster](mailto:james.forsterer@gmail.com) | MIT |
| [rgb](https://github.com/kornelski/rust-rgb) | 0.8.50 | [Kornel Lesiński](mailto:kornel@geekhood.net) and [James Forster](mailto:james.forsterer@gmail.com) | MIT |
| [rustc-hash](https://github.com/rust-lang-nursery/rustc-hash) | 1.1.0 | The Rust Project Developers | Apache-2.0 or MIT |
| [tap](https://github.com/myrrlyn/tap) | 1.0.1 | [Elliott Linder](mailto:elliott.darfink@gmail.com) and [myrrlyn](mailto:self@myrrlyn.dev) | MIT |
| [tempfile](https://github.com/Stebalien/tempfile) | 3.12.0 | [Steven Allen](mailto:steven@stebalien.com), The Rust Project Developers, [Ashley Mannix](mailto:ashleymannix@live.com.au), and [Jason White](mailto:me@jasonwhite.io) | Apache-2.0 or MIT |
| [terminal_size](https://github.com/eminence/terminal-size) | 0.3.0 | [Andrew Chin](mailto:achin@eminence32.net) | Apache-2.0 or MIT |
| [unicode-width](https://github.com/unicode-rs/unicode-width) | 0.1.13 | [kwantam](mailto:kwantam@gmail.com) and [Manish Goregaokar](mailto:manishsmail@gmail.com) | Apache-2.0 or MIT |
| [write_atomic](https://github.com/Blobfolio/write_atomic) | 0.5.0 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [write_atomic](https://github.com/Blobfolio/write_atomic) | 0.5.1 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL |
| [wyz](https://github.com/myrrlyn/wyz) | 0.5.1 | [myrrlyn](mailto:self@myrrlyn.dev) | MIT |
| [zerocopy](https://github.com/google/zerocopy) | 0.7.35 | [Joshua Liebow-Feeser](mailto:joshlf@google.com) | Apache-2.0, BSD-2-Clause, or MIT |
4 changes: 2 additions & 2 deletions flaca/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "flaca"
version = "3.1.6"
version = "3.1.7"
license = "WTFPL"
authors = ["Josh Stoik <josh@blobfolio.com>"]
edition = "2021"
Expand Down Expand Up @@ -125,7 +125,7 @@ version = "*"
path = "../flapfli"

[dependencies.fyi_msg]
version = "0.13.*"
version = "0.14.*"
features = [ "progress" ]

[dependencies.mozjpeg-sys]
Expand Down
5 changes: 5 additions & 0 deletions flaca/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ pub fn main() {
fn build_exts() {
let out = format!(
r"
/// # Extension: JPEG.
const E_JPEG: Extension = {};
/// # Extension: JPG.
const E_JPG: Extension = {};
/// # Extension: PNG.
const E_PNG: Extension = {};
",
Extension::codegen(b"jpeg"),
Expand Down
49 changes: 39 additions & 10 deletions flaca/src/image/jpegtran.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,23 @@ pub(super) struct EncodedJPEG {
impl Deref for EncodedJPEG {
type Target = [u8];

#[allow(clippy::cast_possible_truncation, unsafe_code)]
#[expect(clippy::cast_possible_truncation, reason = "False positive.")]
#[expect(unsafe_code, reason = "For slice from raw.")]
fn deref(&self) -> &Self::Target {
if self.is_null() { &[] }
else {
// Safety: the pointer is non-null.
unsafe { std::slice::from_raw_parts(self.buf, self.size as usize) }
}
}
}

impl Drop for EncodedJPEG {
#[allow(unsafe_code)]
#[expect(unsafe_code, reason = "For FFI.")]
fn drop(&mut self) {
if ! self.buf.is_null() {
// Safety: the pointer is non-null and was created by C, so if
// anybody knows what to do with it, C should!
unsafe { libc::free(self.buf.cast::<c_void>()); }
self.buf = std::ptr::null_mut(); // Probably unnecessary?
}
Expand Down Expand Up @@ -117,7 +121,8 @@ impl EncodedJPEG {



#[allow(unsafe_code, clippy::inline_always)]
#[expect(clippy::inline_always, reason = "For performance.")]
#[expect(unsafe_code, reason = "For FFI.")]
#[inline(always)]
/// # Jpegtran (Memory Mode)
///
Expand Down Expand Up @@ -162,6 +167,7 @@ pub(super) fn optimize(src: &[u8]) -> Option<EncodedJPEG> {
let mut srcinfo = JpegSrcInfo::from(src);
let mut dstinfo = JpegDstInfo::from(&mut srcinfo);

// Safety: these are FFI calls…
unsafe {
// Load the source file.
jpeg_mem_src(&mut srcinfo.cinfo, srcinfo.raw.as_ptr(), src_size);
Expand All @@ -179,15 +185,18 @@ pub(super) fn optimize(src: &[u8]) -> Option<EncodedJPEG> {
}

// Read source file as DCT coefficients.
// Safety: this is an FFI call…
let src_coef_arrays: *mut jvirt_barray_ptr = unsafe {
jpeg_read_coefficients(&mut srcinfo.cinfo)
};

// Initialize destination compression parameters from source values.
// Safety: this is an FFI call…
unsafe { jpeg_copy_critical_parameters(&srcinfo.cinfo, &mut dstinfo.cinfo); }

// Adjust destination parameters if required by transform options, and sync
// the coefficient arrays.
// Safety: this is an FFI call…
let dst_coef_arrays: *mut jvirt_barray_ptr = unsafe {
jtransform_adjust_parameters(
&mut srcinfo.cinfo,
Expand All @@ -202,6 +211,7 @@ pub(super) fn optimize(src: &[u8]) -> Option<EncodedJPEG> {

// Compress!
let mut out = EncodedJPEG::new();
// Safety: these are FFI calls…
unsafe {
// Enable "progressive".
jpeg_simple_progression(&mut dstinfo.cinfo);
Expand Down Expand Up @@ -230,6 +240,7 @@ pub(super) fn optimize(src: &[u8]) -> Option<EncodedJPEG> {
// The decompression will have finished much earlier, but we had to wait
// to call this deconstructor until now because of all the shared
// references.
// Safety: this is an FFI call…
unsafe { jpeg_finish_decompress(&mut srcinfo.cinfo); }

// Return it if we got it!
Expand All @@ -245,20 +256,27 @@ pub(super) fn optimize(src: &[u8]) -> Option<EncodedJPEG> {
/// The abstraction is primarily used to ensure the C-related resources are
/// correctly broken down on drop.
struct JpegSrcInfo<'a> {
/// # Source Data.
raw: &'a [u8],

/// # Decompressor.
cinfo: jpeg_decompress_struct,

/// # Error Instance.
err: Box<jpeg_error_mgr>,
}

impl<'a> From<&'a [u8]> for JpegSrcInfo<'a> {
#[allow(unsafe_code)]
#[expect(unsafe_code, reason = "For FFI.")]
fn from(raw: &'a [u8]) -> Self {
let mut out = Self {
raw,
// Safety: the subsequent FFI call expects zeroed memory.
cinfo: unsafe { std::mem::zeroed() },
err: new_err(),
};

// Safety: and here is that FFI call…
unsafe {
// Set up the error, then the struct.
out.cinfo.common.err = std::ptr::addr_of_mut!(*out.err);
Expand All @@ -270,8 +288,9 @@ impl<'a> From<&'a [u8]> for JpegSrcInfo<'a> {
}

impl<'a> Drop for JpegSrcInfo<'a> {
#[allow(unsafe_code)]
#[expect(unsafe_code, reason = "For FFI.")]
fn drop(&mut self) {
// Safety: mozjpeg handles deallocation itself.
unsafe { jpeg_destroy_decompress(&mut self.cinfo); }
}
}
Expand All @@ -286,21 +305,28 @@ impl<'a> Drop for JpegSrcInfo<'a> {
/// On the surface, this looks almost exactly like the `JpegSrcInfo` wrapper,
/// but its error is a raw pointer because `mozjpeg` is really weird. Haha.
struct JpegDstInfo {
/// # Compressor.
cinfo: jpeg_compress_struct,

/// # Error Instance.
err: NonNull<jpeg_error_mgr>,

/// # Pinned Data.
_pin: PhantomPinned,
}

impl From<&mut JpegSrcInfo<'_>> for JpegDstInfo {
#[allow(unsafe_code)]
#[expect(unsafe_code, reason = "For FFI.")]
fn from(src: &mut JpegSrcInfo<'_>) -> Self {
let mut out = Self {
// Safety: the subsequent FFI call requires zeroed memory.
cinfo: unsafe { std::mem::zeroed() },
// Safety: boxes point somewhere!
err: unsafe { NonNull::new_unchecked(Box::into_raw(new_err())) },
_pin: PhantomPinned,
};

// Safety: these are FFI calls…
unsafe {
// Set up the error, then the struct.
out.cinfo.common.err = out.err.as_ptr();
Expand All @@ -320,8 +346,9 @@ impl From<&mut JpegSrcInfo<'_>> for JpegDstInfo {
}

impl Drop for JpegDstInfo {
#[allow(unsafe_code)]
#[expect(unsafe_code, reason = "For FFI.")]
fn drop(&mut self) {
// Safety: mozjpeg handles deallocation itself.
unsafe {
jpeg_destroy_compress(&mut self.cinfo);
let _ = Box::from_raw(self.err.as_ptr());
Expand All @@ -330,7 +357,7 @@ impl Drop for JpegDstInfo {
}

impl JpegDstInfo {
#[allow(unsafe_code)]
#[expect(unsafe_code, reason = "For FFI.")]
/// # Finish Compression!
///
/// This finishes writing the new image, consuming the details struct in
Expand All @@ -339,6 +366,7 @@ impl JpegDstInfo {
/// A simple `true`/`false` boolean is returned to indicate (likely)
/// success.
fn finish(mut self) -> bool {
// Safety: mozjpeg handles deallocation itself.
unsafe {
jpeg_finish_compress(&mut self.cinfo);
0 == (*self.cinfo.common.err).msg_code
Expand All @@ -348,7 +376,8 @@ impl JpegDstInfo {



#[allow(clippy::unnecessary_box_returns, unsafe_code)]
#[expect(clippy::unnecessary_box_returns, reason = "We want a box.")]
#[expect(unsafe_code, reason = "For FFI.")]
/// # New Unwinding Error.
///
/// Mozjpeg is largely designed to panic anytime there's an error instead of
Expand All @@ -360,6 +389,7 @@ impl JpegDstInfo {
/// Shout out to the [mozjpeg](https://github.com/ImageOptim/mozjpeg-rust/blob/main/src/errormgr.rs)
/// crate for the inspiration!
fn new_err() -> Box<jpeg_error_mgr> {
// Safety: the FFI call requires zeroed memory to start from.
unsafe {
let mut err = Box::new(std::mem::zeroed());
jpeg_std_error(&mut err);
Expand All @@ -376,7 +406,6 @@ fn new_err() -> Box<jpeg_error_mgr> {
extern "C-unwind" fn silence_message(_cinfo: &mut jpeg_common_struct, _msg_level: c_int) {}

#[cold]
#[allow(unsafe_code)]
/// # Error Exit.
///
/// Emit an unwinding panic so we can recover somewhat gracefully from mozjpeg
Expand Down
15 changes: 7 additions & 8 deletions flaca/src/image/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::num::NonZeroU32;


#[repr(u8)]
#[allow(clippy::redundant_pub_crate)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
/// # Image Kind.
///
Expand All @@ -26,14 +25,14 @@ pub(crate) enum ImageKind {
}

impl ImageKind {
#[allow(clippy::inline_always)]
#[expect(clippy::inline_always, reason = "For performance.")]
#[inline(always)]
/// # Supports JPEG?
pub(crate) const fn supports_jpeg(self) -> bool {
matches!(self, Self::All | Self::Jpeg)
}

#[allow(clippy::inline_always)]
#[expect(clippy::inline_always, reason = "For performance.")]
#[inline(always)]
/// # Supports PNG?
pub(crate) const fn supports_png(self) -> bool {
Expand All @@ -42,7 +41,7 @@ impl ImageKind {
}

impl ImageKind {
#[allow(clippy::inline_always)]
#[expect(clippy::inline_always, reason = "For performance.")]
#[inline(always)]
/// # Is JPEG?
pub(crate) fn is_jpeg(src: &[u8]) -> bool {
Expand All @@ -56,7 +55,7 @@ impl ImageKind {
)
}

#[allow(clippy::inline_always)]
#[expect(clippy::inline_always, reason = "For performance.")]
#[inline(always)]
/// # Is PNG?
pub(crate) fn is_png(src: &[u8]) -> bool {
Expand Down Expand Up @@ -203,12 +202,12 @@ mod tests {
}

#[test]
#[expect(clippy::cognitive_complexity, reason = "It is what it is.")]
fn t_parse() {
macro_rules! test_kind {
($($file:literal $ty:expr),+) => ($(
let raw = match std::fs::read($file) {
Ok(f) => f,
Err(_) => panic!("Unable to open {}.", $file),
let Ok(raw) = std::fs::read($file) else {
panic!("Unable to open {}.", $file);
};
match $ty {
Some(ImageKind::Jpeg) => {
Expand Down
4 changes: 2 additions & 2 deletions flaca/src/image/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use super::EncodingError;



#[allow(clippy::inline_always)] // This is the hottest path we've got!
#[expect(clippy::inline_always, reason = "For performance.")]
#[inline(always)]
/// # Encode Image.
///
Expand Down Expand Up @@ -61,7 +61,7 @@ pub(super) fn encode(file: &Path, kinds: ImageKind)

// Encoding checks this explicitly, but debug asserts are nothing if
// not redundant!
debug_assert!(ImageKind::is_jpeg(&raw));
debug_assert!(ImageKind::is_jpeg(&raw), "BUG: raw was unexpectedly corrupted");
}
// Something else entirely?
else { return Err(EncodingError::Format); }
Expand Down
Loading

0 comments on commit e26ee4f

Please sign in to comment.