Use ArrayVec instead of const cap Vec

Reduces size in memory by a few bytes and entirely avoids heap
allocation
This commit is contained in:
Luracasmus 2025-12-07 15:54:34 +01:00
parent 5937ae190f
commit ddfe17d609
No known key found for this signature in database
GPG key ID: B15AEB0540D7693F
4 changed files with 52 additions and 23 deletions

7
Cargo.lock generated
View file

@ -58,6 +58,12 @@ dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "autocfg"
version = "1.5.0"
@ -408,6 +414,7 @@ checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
name = "oxipng"
version = "10.0.0"
dependencies = [
"arrayvec",
"bitvec",
"clap",
"crossbeam-channel",

View file

@ -45,6 +45,7 @@ libdeflater = "1.25.0"
log = "0.4.28"
bitvec = "1.0.1"
rustc-hash = "2.1.1"
arrayvec = "0.7.6"
[dependencies.env_logger]
optional = true

View file

@ -1,4 +1,4 @@
use std::io::Write;
use arrayvec::ArrayVec;
use crate::{
PngResult,
@ -50,17 +50,33 @@ impl Frame {
/// Construct the data for a fcTL chunk using the given sequence number
#[must_use]
pub fn fctl_data(&self, sequence_number: u32) -> Vec<u8> {
let mut byte_data = Vec::with_capacity(26);
byte_data.write_all(&sequence_number.to_be_bytes()).unwrap();
byte_data.write_all(&self.width.to_be_bytes()).unwrap();
byte_data.write_all(&self.height.to_be_bytes()).unwrap();
byte_data.write_all(&self.x_offset.to_be_bytes()).unwrap();
byte_data.write_all(&self.y_offset.to_be_bytes()).unwrap();
byte_data.write_all(&self.delay_num.to_be_bytes()).unwrap();
byte_data.write_all(&self.delay_den.to_be_bytes()).unwrap();
byte_data.push(self.dispose_op);
byte_data.push(self.blend_op);
pub fn fctl_data(&self, sequence_number: u32) -> ArrayVec<u8, 26> {
let mut byte_data = const { ArrayVec::<_, 26>::new_const() };
byte_data
.try_extend_from_slice(&sequence_number.to_be_bytes())
.unwrap();
byte_data
.try_extend_from_slice(&self.width.to_be_bytes())
.unwrap();
byte_data
.try_extend_from_slice(&self.height.to_be_bytes())
.unwrap();
byte_data
.try_extend_from_slice(&self.x_offset.to_be_bytes())
.unwrap();
byte_data
.try_extend_from_slice(&self.y_offset.to_be_bytes())
.unwrap();
byte_data
.try_extend_from_slice(&self.delay_num.to_be_bytes())
.unwrap();
byte_data
.try_extend_from_slice(&self.delay_den.to_be_bytes())
.unwrap();
byte_data
.try_extend_from_slice(&[self.dispose_op, self.blend_op])
.unwrap();
byte_data
}

View file

@ -1,5 +1,6 @@
use std::{fs, io::Write, path::Path, sync::Arc};
use std::{fs, path::Path, sync::Arc};
use arrayvec::ArrayVec;
use bitvec::bitarr;
use libdeflater::{CompressionLvl, Compressor};
use log::warn;
@ -164,18 +165,22 @@ impl PngData {
// PNG header
let mut output = vec![0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
// IHDR
let mut ihdr_data = Vec::with_capacity(13);
ihdr_data.write_all(&self.raw.ihdr.width.to_be_bytes()).ok();
let mut ihdr_data = const { ArrayVec::<_, 13>::new_const() };
ihdr_data
.write_all(&self.raw.ihdr.height.to_be_bytes())
.ok();
ihdr_data.write_all(&[self.raw.ihdr.bit_depth as u8]).ok();
.try_extend_from_slice(&self.raw.ihdr.width.to_be_bytes())
.unwrap();
ihdr_data
.write_all(&[self.raw.ihdr.color_type.png_header_code()])
.ok();
ihdr_data.write_all(&[0]).ok(); // Compression -- deflate
ihdr_data.write_all(&[0]).ok(); // Filter method -- 5-way adaptive filtering
ihdr_data.write_all(&[self.raw.ihdr.interlaced as u8]).ok();
.try_extend_from_slice(&self.raw.ihdr.height.to_be_bytes())
.unwrap();
ihdr_data
.try_extend_from_slice(&[
self.raw.ihdr.bit_depth as u8,
self.raw.ihdr.color_type.png_header_code(),
0, // Compression -- deflate
0, // Filter method -- 5-way adaptive filtering
self.raw.ihdr.interlaced as u8,
])
.unwrap();
write_png_block(b"IHDR", &ihdr_data, &mut output);
// Ancillary chunks - split into those that come before IDAT and those that come after
let mut aux_split = self.aux_chunks.split(|c| &c.name == b"IDAT");