Skip to main content

ChainOutcome

Struct ChainOutcome 

Source
pub struct ChainOutcome {
    pub bytes: Vec<u8>,
    pub inner_ok: bool,
    pub outer_ok: bool,
    pub crc_ok: bool,
    pub crc_present: bool,
    pub outer_present: bool,
    pub outer_corrected_bytes: Option<u32>,
    pub inner_out_bits: Vec<u8>,
}
Expand description

The outcome of decoding one logical block: the recovered bytes plus each stage’s success, reported separately.

The concatenated scheme has two independent decoders, and folding them into one flag destroys the only signal that distinguishes a marginal link from a failing one. Errors the inner code corrects never reach the outer code, so inner_ok == false with outer_ok == true is a link running hot but still delivering — precisely the state a pre-FEC error rate is meant to surface, and indistinguishable from success once folded.

Use is_valid to decide whether to accept the block; the individual flags are diagnostics.

Fields§

§bytes: Vec<u8>

The recovered info bytes, CRC stripped.

§inner_ok: bool

Every inner-FEC block converged. Always true for InnerFec::None, and for the convolutional arm, whose soft Viterbi has no per-block convergence flag — the outer code and CRC decide.

§outer_ok: bool

Every outer-FEC block decoded. Always true for OuterFec::None.

§crc_ok: bool

The block’s CRC checked.

§crc_present: bool

Whether the configuration provides a CRC at all. Without this, crc_ok is ambiguous: CrcKind::None reports true because there was nothing to fail, not because anything was verified.

§outer_present: bool

Whether the configuration provides an outer code at all, on the same reasoning as crc_present.

§outer_corrected_bytes: Option<u32>

How many codeword bytes the outer decoder corrected across this block, or None when the outer code reports no such count — every arm but OuterFec::ReedSolomon, since BCH is binary and corrects bits.

The measurement outer_ok cannot make. That flag saturates — a codeword one error from the cliff and a pristine one both read true — whereas this rises smoothly with the channel, so it shows a link approaching failure while it is still delivering. It is the count real DVB-T receivers report, and it costs nothing: the Forney correction loop already computed every magnitude.

Counted only over codewords that decoded. A block the code could not correct contributes nothing, because a correction the decoder does not trust is not a correction to report. So on a frame with outer_ok == false this is a lower bound; read the two together.

§inner_out_bits: Vec<u8>

What the inner decoder produced, untrimmed — every bit it decided, including the zero-padding tail of the final codeword that the block plan discards before the outer decoder sees it.

Kept rather than dropped so a caller can compare it against a re-encode of the recovered message and obtain a post-inner-FEC bit error rate instead of a pass/fail flag. Costs nothing: the vector is already allocated, and is moved out rather than copied.

Untrimmed because re-encoding a trimmed copy zero-pads that tail back to zero, which silently asserts the decoder got the padding right. For a 184-byte payload on the default ladder that is 168 bits of 5120 — enough to paint a real decoder error Clean in a correction map, and far too few to notice in one. Consumers that want only the bits the outer decoder saw take [..plan.outer_il_bits]; [bit_error_rate] compares over the shorter of its two inputs, so the trim is implicit there.

Implementations§

Source§

impl ChainOutcome

Source

pub fn is_valid(&self) -> bool

Whether the recovered bytes can be trusted, judged by the strongest end-to-end check the configuration actually provides.

inner_ok is deliberately not part of this. It reports whether the inner decoder’s parity checks converged — how hard it worked, not whether the result is right. Requiring it discards frames whose payload is verifiably correct: measured across a noise sweep, a CRC-carrying link delivers byte-exact payloads with inner_ok == false over a wide band, and rejecting those costs real sensitivity for nothing.

The precedence:

  • A CRC decides on its own. It is computed over the recovered payload end to end, so passing it means the bytes are right whatever the stages beneath did — including an outer decoder that reported a block it could not correct.
  • Otherwise the outer code decides. DVB-T carries no CRC (CrcKind::None), so its Reed–Solomon stage is the integrity check; RS reports failure when it cannot correct a codeword.
  • Otherwise inner_ok is all there is. A link with neither a CRC nor an outer code has only the inner decoder’s convergence to go on, and dropping it there would accept anything.

Trait Implementations§

Source§

impl Clone for ChainOutcome

Source§

fn clone(&self) -> ChainOutcome

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ChainOutcome

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for ChainOutcome

Source§

impl PartialEq for ChainOutcome

Source§

fn eq(&self, other: &ChainOutcome) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for ChainOutcome

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.