use super::super::build::CodeBlock;
use super::super::decode::DecompositionStorage;
use super::pipeline::PHASE_LIMIT_MAGREF;
use super::state::HtBlockDecodeContext;
use super::stats::HtBlockDecodeStats;
use super::validation::decode_segments_validated_with_scratch_for_phase;
use super::{collect_code_block_data_into, HtCodeBlockSegments};
use crate::error::{bail, DecodingError, Result};
#[expect(
clippy::too_many_arguments,
reason = "this internal facade preserves the established decode configuration and observer inputs"
)]
pub(crate) fn decode_with_stats(
code_block: &CodeBlock,
total_bitplanes: u8,
stripe_causal: bool,
ctx: &mut HtBlockDecodeContext,
storage: &DecompositionStorage<'_>,
strict: bool,
stats: Option<&mut HtBlockDecodeStats>,
profile_enabled: bool,
) -> Result<()> {
ctx.reset(code_block)?;
if total_bitplanes == 0 {
return Ok(());
}
if total_bitplanes > 31 {
bail!(DecodingError::TooManyBitplanes);
}
let actual_bitplanes = if strict {
total_bitplanes
.checked_sub(code_block.missing_bit_planes)
.ok_or(DecodingError::InvalidBitplaneCount)?
} else {
total_bitplanes.saturating_sub(code_block.missing_bit_planes)
};
let max_coding_passes = if actual_bitplanes == 0 {
0
} else {
1 + 3 * (actual_bitplanes - 1)
};
if code_block.number_of_coding_passes > max_coding_passes && strict {
bail!(DecodingError::TooManyCodingPasses);
}
if code_block.number_of_coding_passes == 0 || actual_bitplanes == 0 {
return Ok(());
}
let (cleanup_length, refinement_length) =
collect_code_block_data_into(code_block, storage, &mut ctx.segment_data)?;
let segments = HtCodeBlockSegments::from_combined_payload(
&ctx.segment_data,
cleanup_length,
refinement_length,
)?;
decode_segments_validated_with_scratch_for_phase::<PHASE_LIMIT_MAGREF>(
&segments,
code_block.missing_bit_planes,
total_bitplanes,
code_block.number_of_coding_passes,
stripe_causal,
strict,
&mut ctx.coefficients,
code_block.rect.width(),
code_block.rect.height(),
code_block.rect.width(),
&mut ctx.scratch,
stats,
profile_enabled,
)
}