From fcf5d8ec06a380b864da578d77d150d036b6b783 Mon Sep 17 00:00:00 2001 From: Moritz Firsching Date: Mon, 23 Dec 2024 10:46:41 +0100 Subject: [PATCH] add try_with_capacity (#75) --- jxl/src/entropy_coding/huffman.rs | 11 ++++----- jxl/src/entropy_coding/hybrid_uint.rs | 2 +- jxl/src/features/patches.rs | 5 ++-- jxl/src/features/spline.rs | 6 ++--- jxl/src/frame/modular/tree.rs | 8 +++---- jxl/src/headers/permutation.rs | 16 +++++-------- jxl/src/icc/header.rs | 5 ++-- jxl/src/icc/stream.rs | 4 ++-- jxl/src/icc/tag.rs | 7 +++--- jxl/src/util.rs | 3 ++- jxl/src/util/vec_helpers.rs | 33 +++++++++++++++++++++++++++ 11 files changed, 62 insertions(+), 38 deletions(-) create mode 100644 jxl/src/util/vec_helpers.rs diff --git a/jxl/src/entropy_coding/huffman.rs b/jxl/src/entropy_coding/huffman.rs index cedf990..371fd65 100644 --- a/jxl/src/entropy_coding/huffman.rs +++ b/jxl/src/entropy_coding/huffman.rs @@ -8,8 +8,7 @@ use std::fmt::Debug; use crate::bit_reader::BitReader; use crate::entropy_coding::decode::*; use crate::error::{Error, Result}; -use crate::util::tracing_wrappers::*; -use crate::util::*; +use crate::util::{tracing_wrappers::*, CeilLog2, NewWithCapacity}; pub const HUFFMAN_MAX_BITS: usize = 15; const TABLE_BITS: usize = 8; @@ -104,7 +103,7 @@ impl Table { TABLE_SIZE ]), (2, _) => { - let mut ret = Vec::with_capacity(TABLE_SIZE); + let mut ret = Vec::new_with_capacity(TABLE_SIZE)?; for _ in 0..(TABLE_SIZE >> 1) { ret.push(TableEntry { bits: 1, @@ -118,7 +117,7 @@ impl Table { Ok(ret) } (3, _) => { - let mut ret = Vec::with_capacity(TABLE_SIZE); + let mut ret = Vec::new_with_capacity(TABLE_SIZE)?; for _ in 0..(TABLE_SIZE >> 2) { ret.push(TableEntry { bits: 1, @@ -140,7 +139,7 @@ impl Table { Ok(ret) } (4, false) => { - let mut ret = Vec::with_capacity(TABLE_SIZE); + let mut ret = Vec::new_with_capacity(TABLE_SIZE)?; for _ in 0..(TABLE_SIZE >> 2) { ret.push(TableEntry { bits: 2, @@ -162,7 +161,7 @@ impl Table { Ok(ret) } (4, true) => { - let mut ret = Vec::with_capacity(TABLE_SIZE); + let mut ret = Vec::new_with_capacity(TABLE_SIZE)?; symbols[2..4].sort_unstable(); for _ in 0..(TABLE_SIZE >> 3) { ret.push(TableEntry { diff --git a/jxl/src/entropy_coding/hybrid_uint.rs b/jxl/src/entropy_coding/hybrid_uint.rs index 9e645c7..2077110 100644 --- a/jxl/src/entropy_coding/hybrid_uint.rs +++ b/jxl/src/entropy_coding/hybrid_uint.rs @@ -6,7 +6,7 @@ use crate::bit_reader::BitReader; use crate::error::Error; -use crate::util::*; +use crate::util::CeilLog2; #[derive(Debug)] pub struct HybridUint { diff --git a/jxl/src/features/patches.rs b/jxl/src/features/patches.rs index 290ce26..f164d70 100644 --- a/jxl/src/features/patches.rs +++ b/jxl/src/features/patches.rs @@ -14,7 +14,7 @@ use crate::{ entropy_coding::decode::Histograms, error::{Error, Result}, frame::DecoderState, - util::tracing_wrappers::*, + util::{tracing_wrappers::*, NewWithCapacity}, }; // Context numbers as specified in Section C.4.5, Listing C.2: @@ -153,8 +153,7 @@ impl PatchesDictionary { let mut next_size = 1; let mut positions: Vec = Vec::new(); let mut blendings = Vec::new(); - let mut ref_positions: Vec = Vec::new(); - ref_positions.try_reserve(num_ref_patch)?; + let mut ref_positions = Vec::new_with_capacity(num_ref_patch)?; for _ in 0..num_ref_patch { let reference = patches_reader.read(br, PatchContext::ReferenceFrame as usize)? as usize; diff --git a/jxl/src/features/spline.rs b/jxl/src/features/spline.rs index 1f64b87..7b5bb68 100644 --- a/jxl/src/features/spline.rs +++ b/jxl/src/features/spline.rs @@ -15,7 +15,7 @@ use crate::{ bit_reader::BitReader, entropy_coding::decode::{unpack_signed, Histograms, Reader}, error::{Error, Result}, - util::{tracing_wrappers::*, CeilLog2}, + util::{tracing_wrappers::*, CeilLog2, NewWithCapacity}, }; const MAX_NUM_CONTROL_POINTS: u32 = 1 << 20; const MAX_NUM_CONTROL_POINTS_PER_PIXEL_RATIO: u32 = 2; @@ -192,7 +192,7 @@ impl QuantizedSpline { max_control_points, )); } - let mut control_points = Vec::with_capacity(num_control_points as usize); + let mut control_points = Vec::new_with_capacity(num_control_points as usize)?; for _ in 0..num_control_points { let x = splines_reader.read_signed(br, CONTROL_POINTS_CONTEXT)? as i64; let y = splines_reader.read_signed(br, CONTROL_POINTS_CONTEXT)? as i64; @@ -237,7 +237,7 @@ impl QuantizedSpline { let area_limit = area_limit(image_size); let mut result = Spline { - control_points: Vec::with_capacity(self.control_points.len() + 1), + control_points: Vec::new_with_capacity(self.control_points.len() + 1)?, ..Default::default() }; diff --git a/jxl/src/frame/modular/tree.rs b/jxl/src/frame/modular/tree.rs index 3bb4247..7cf7f81 100644 --- a/jxl/src/frame/modular/tree.rs +++ b/jxl/src/frame/modular/tree.rs @@ -10,7 +10,7 @@ use crate::{ bit_reader::BitReader, entropy_coding::decode::Histograms, error::{Error, Result}, - util::tracing_wrappers::*, + util::{tracing_wrappers::*, NewWithCapacity}, }; #[allow(dead_code)] @@ -115,11 +115,9 @@ impl Tree { tree_reader.check_final_state()?; let num_properties = max_property as usize + 1; - let mut property_ranges = vec![]; - property_ranges.try_reserve(num_properties * tree.len())?; + let mut property_ranges = Vec::new_with_capacity(num_properties * tree.len())?; property_ranges.resize(num_properties * tree.len(), (i32::MIN, i32::MAX)); - let mut height = vec![]; - height.try_reserve(tree.len())?; + let mut height = Vec::new_with_capacity(tree.len())?; height.resize(tree.len(), 0); for i in 0..tree.len() { const HEIGHT_LIMIT: usize = 2048; diff --git a/jxl/src/headers/permutation.rs b/jxl/src/headers/permutation.rs index d12b584..9449667 100644 --- a/jxl/src/headers/permutation.rs +++ b/jxl/src/headers/permutation.rs @@ -6,7 +6,7 @@ use crate::bit_reader::BitReader; use crate::entropy_coding::decode::Reader; use crate::error::{Error, Result}; -use crate::util::{tracing_wrappers::instrument, value_of_lowest_1_bit, CeilLog2}; +use crate::util::{tracing_wrappers::instrument, value_of_lowest_1_bit, CeilLog2, NewWithCapacity}; #[derive(Debug, PartialEq, Default)] pub struct Permutation(pub Vec); @@ -41,8 +41,7 @@ impl Permutation { return Err(Error::InvalidPermutationSize { size, skip, end }); } - let mut lehmer = Vec::new(); - lehmer.try_reserve(end as usize)?; + let mut lehmer = Vec::new_with_capacity(end as usize)?; let mut prev_val = 0u32; for idx in skip..(skip + end) { @@ -59,8 +58,7 @@ impl Permutation { } // Initialize the full permutation vector with skipped elements intact - let mut permutation: Vec = Vec::new(); - permutation.try_reserve((size - skip) as usize)?; + let mut permutation = Vec::new_with_capacity((size - skip) as usize)?; permutation.extend(0..size); // Decode the Lehmer code into the slice starting at `skip` @@ -88,15 +86,13 @@ fn decode_lehmer_code(code: &[u32], permutation_slice: &[u32]) -> Result Result Resu let header_size = output_size.min(ICC_HEADER_SIZE); let header_data = data_stream.read_to_vec_exact(header_size as usize)?; - let mut profile = Vec::new(); - profile.try_reserve(output_size as usize)?; + let mut profile = Vec::new_with_capacity(output_size as usize)?; for (idx, &e) in header_data.iter().enumerate() { let p = predict_header(idx, output_size as u32, &header_data); diff --git a/jxl/src/icc/stream.rs b/jxl/src/icc/stream.rs index fd8bf4a..ff6453b 100644 --- a/jxl/src/icc/stream.rs +++ b/jxl/src/icc/stream.rs @@ -11,6 +11,7 @@ use crate::bit_reader::*; use crate::entropy_coding::decode::{Histograms, Reader}; use crate::error::{Error, Result}; use crate::util::tracing_wrappers::{instrument, warn}; +use crate::util::NewWithCapacity; fn read_varint(mut read_one: impl FnMut() -> Result) -> Result { let mut value = 0u64; @@ -129,8 +130,7 @@ impl<'br, 'buf, 'hist> IccStream<'br, 'buf, 'hist> { return Err(Error::IccEndOfStream); } - let mut out = Vec::new(); - out.try_reserve(len)?; + let mut out = Vec::new_with_capacity(len)?; for _ in 0..len { out.push(self.read_one()?); diff --git a/jxl/src/icc/tag.rs b/jxl/src/icc/tag.rs index c69bc6d..2c9b232 100644 --- a/jxl/src/icc/tag.rs +++ b/jxl/src/icc/tag.rs @@ -9,6 +9,7 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use crate::error::{Error, Result}; use crate::util::tracing_wrappers::warn; +use crate::util::NewWithCapacity; use super::{read_varint_from_reader, IccStream, ICC_HEADER_SIZE}; @@ -96,8 +97,7 @@ pub(super) fn read_tag_list( fn shuffle_w2(bytes: &[u8]) -> Result> { let len = bytes.len(); - let mut out = Vec::new(); - out.try_reserve(len)?; + let mut out = Vec::new_with_capacity(len)?; let height = len / 2; let odd = len % 2; @@ -113,8 +113,7 @@ fn shuffle_w2(bytes: &[u8]) -> Result> { fn shuffle_w4(bytes: &[u8]) -> Result> { let len = bytes.len(); - let mut out = Vec::new(); - out.try_reserve(len)?; + let mut out = Vec::new_with_capacity(len)?; let step = len / 4; let wide_count = len % 4; diff --git a/jxl/src/util.rs b/jxl/src/util.rs index fd00579..9ac8ca9 100644 --- a/jxl/src/util.rs +++ b/jxl/src/util.rs @@ -7,14 +7,15 @@ pub mod test; mod bits; -#[allow(unused)] mod concat_slice; mod log2; mod shift_right_ceil; pub mod tracing_wrappers; +mod vec_helpers; pub use bits::*; #[allow(unused)] pub use concat_slice::*; pub use log2::*; pub use shift_right_ceil::*; +pub use vec_helpers::*; diff --git a/jxl/src/util/vec_helpers.rs b/jxl/src/util/vec_helpers.rs new file mode 100644 index 0000000..e9af8c8 --- /dev/null +++ b/jxl/src/util/vec_helpers.rs @@ -0,0 +1,33 @@ +// Copyright (c) the JPEG XL Project Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO(firsching): as soon as "Vec::try_with_capacity" is available from the +// standard library use this instead of the functions here. +pub trait NewWithCapacity { + type Output; + type Error; + fn new_with_capacity(capacity: usize) -> Result; +} + +impl NewWithCapacity for Vec { + type Output = Vec; + type Error = std::collections::TryReserveError; + + fn new_with_capacity(capacity: usize) -> Result { + let mut vec = Vec::new(); + vec.try_reserve(capacity)?; + Ok(vec) + } +} + +impl NewWithCapacity for String { + type Output = String; + type Error = std::collections::TryReserveError; + fn new_with_capacity(capacity: usize) -> Result { + let mut s = String::new(); + s.try_reserve(capacity)?; + Ok(s) + } +}