qubit_codec/transcode/engine/decode_invalid_action.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Invalid-decode actions returned by buffered decoder policy hooks.
9
10use core::num::NonZeroUsize;
11
12use crate::Codec;
13
14/// Invalid-decode action for a codec-backed decode hook.
15pub type DecodeInvalidActionOf<C> = DecodeInvalidAction<<C as Codec>::Value>;
16
17/// Action selected after a codec reports invalid encoded input.
18///
19/// Incomplete input is not a policy action. Codecs report it with
20/// [`crate::DecodeFailure::Incomplete`], and the decode engine converts it
21/// directly into [`crate::TranscodeStatus::NeedInput`].
22///
23/// # Type Parameters
24///
25/// - `Value`: Decoded output value type.
26#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
27#[non_exhaustive]
28pub enum DecodeInvalidAction<Value> {
29 /// Reject the current invalid input.
30 ///
31 /// The decode engine reports the original codec decode error as
32 /// [`crate::TranscodeDecodeError::Domain`] at the current input index.
33 Reject,
34
35 /// Consume invalid input without producing output.
36 ///
37 /// `consumed` must not exceed the hook context's available input count.
38 /// Over-consuming is a hook contract violation and panics in the engine.
39 Skip {
40 /// Source units to consume.
41 consumed: NonZeroUsize,
42 },
43
44 /// Produce one replacement value and consume source units.
45 ///
46 /// `consumed` must not exceed the hook context's available input count.
47 /// Over-consuming is a hook contract violation and panics in the engine.
48 Emit {
49 /// Value to write to the output buffer.
50 value: Value,
51 /// Source units to consume.
52 consumed: NonZeroUsize,
53 },
54}
55
56impl<Value> DecodeInvalidAction<Value> {
57 /// Validates a policy-reported consumed source-unit count against available
58 /// input.
59 ///
60 /// # Parameters
61 ///
62 /// - `consumed`: Source units requested by the concrete policy.
63 /// - `available`: Source units visible from the current decode cursor.
64 ///
65 /// # Returns
66 ///
67 /// Returns the validated non-zero consumed count.
68 ///
69 /// # Panics
70 ///
71 /// Panics when `available == 0` or when `consumed > available`.
72 #[inline(always)]
73 #[must_use]
74 pub(super) fn bound_consumed(consumed: NonZeroUsize, available: usize) -> NonZeroUsize {
75 assert!(available > 0, "DecodeInvalidAction cannot consume empty input",);
76 assert!(
77 consumed.get() <= available,
78 "DecodeInvalidAction consumed units must not exceed available input",
79 );
80 consumed
81 }
82}