From 02d91c4a03a7f5f7fa3840bcfe57007f566f69dc Mon Sep 17 00:00:00 2001 From: ChubbyChipmunk77 Date: Mon, 29 Dec 2025 00:00:38 +0530 Subject: [PATCH 1/3] REFACTOR: 1. simplified verify_parity function. 2.Improved documentation for public function validate_cc_pair. 3. Added constant for 0x7F. --- src/rust/src/lib.rs | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 9f267c7b3..7a991d124 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -251,10 +251,31 @@ extern "C" fn ccxr_process_cc_data( ret } -/// Returns `true` if cc_block pair is valid -/// -/// For CEA-708 data, only cc_valid is checked -/// For CEA-608 data, parity is also checked +// Validates a closed caption block pair for both CEA-608 and CEA-708 data. +// +// # Arguments +// cc_block - A mutable slice containing exactly 3 bytes representing a CC block +// +// # Returns +// true if the CC block is valid and should be processed +// false if the CC block should be ignored +// +// # Behavior +// 1. Header Validation: +// - Checks the cc_valid flag (bit 2 of cc_block[0]). If 0, returns false immediately. +// - extracts the cc_type (bits 0-1 of cc_block[0]). +// +// 2. CEA-708 (Type 2 or 3): +// - No further validation is required beyond the cc_valid flag. Returns true. +// +// 3. CEA-608 (Type 0 or 1): +// - Critical Parity Check: Validates parity for the second data byte (cc_block[2]). +// If this fails, the entire pair is deemed corrupt, and the function returns false. +// - Sanitization: Validates parity for the first data byte (cc_block[1]). +// If this fails (but byte 2 was valid), cc_block[1] is overwritten with CC_SOLID_BLANK (0x7F). + +const CC_SOLID_BLANK: u8 = 0x7F; + pub fn validate_cc_pair(cc_block: &mut [u8]) -> bool { let cc_valid = (cc_block[0] & 4) >> 2; let cc_type = cc_block[0] & 3; @@ -270,7 +291,7 @@ pub fn validate_cc_pair(cc_block: &mut [u8]) -> bool { if verify_parity(cc_block[1]) { // If the first byte doesn't pass parity, // we replace it with a solid blank and process the pair. - cc_block[1] = 0x7F; + cc_block[1] = CC_SOLID_BLANK; } } true @@ -280,10 +301,7 @@ pub fn validate_cc_pair(cc_block: &mut [u8]) -> bool { /// /// CC uses odd parity (i.e., # of 1's in byte is odd.) pub fn verify_parity(data: u8) -> bool { - if data.count_ones() & 1 == 1 { - return true; - } - false + data.count_ones() & 1 == 1 } /// Process CC data according to its type @@ -295,8 +313,8 @@ pub fn do_cb_dtvcc(ctx: &mut lib_cc_decode, dtvcc: &mut Dtvcc, cc_block: &[u8]) if ctx.write_format != ccx_output_format::CCX_OF_DVDRAW && ctx.write_format != ccx_output_format::CCX_OF_RAW && (cc_block[0] == 0xFA || cc_block[0] == 0xFC || cc_block[0] == 0xFD) - && (cc_block[1] & 0x7F) == 0 - && (cc_block[2] & 0x7F) == 0 + && (cc_block[1] & CC_SOLID_BLANK) == 0 + && (cc_block[2] & CC_SOLID_BLANK) == 0 { return true; } @@ -527,7 +545,7 @@ mod test { let mut cc_block = [0x15, 0x2F, 0x7D]; assert!(validate_cc_pair(&mut cc_block)); // Check for replaced bit when 1st byte doesn't pass parity - assert_eq!(cc_block[1], 0x7F); + assert_eq!(cc_block[1], CC_SOLID_BLANK); // Invalid CEA-608 data let mut cc_block = [0x15, 0x2F, 0x5E]; From 7f55ae5c1d386533c9beda7d6bc5326013cf06dc Mon Sep 17 00:00:00 2001 From: ChubbyChipmunk77 Date: Mon, 29 Dec 2025 21:30:40 +0530 Subject: [PATCH 2/3] Fixed semantic naming and update doc comments --- src/rust/src/lib.rs | 55 +++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 7a991d124..0be5f2bf5 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -251,28 +251,28 @@ extern "C" fn ccxr_process_cc_data( ret } -// Validates a closed caption block pair for both CEA-608 and CEA-708 data. -// -// # Arguments -// cc_block - A mutable slice containing exactly 3 bytes representing a CC block -// -// # Returns -// true if the CC block is valid and should be processed -// false if the CC block should be ignored -// -// # Behavior -// 1. Header Validation: -// - Checks the cc_valid flag (bit 2 of cc_block[0]). If 0, returns false immediately. -// - extracts the cc_type (bits 0-1 of cc_block[0]). -// -// 2. CEA-708 (Type 2 or 3): -// - No further validation is required beyond the cc_valid flag. Returns true. -// -// 3. CEA-608 (Type 0 or 1): -// - Critical Parity Check: Validates parity for the second data byte (cc_block[2]). -// If this fails, the entire pair is deemed corrupt, and the function returns false. -// - Sanitization: Validates parity for the first data byte (cc_block[1]). -// If this fails (but byte 2 was valid), cc_block[1] is overwritten with CC_SOLID_BLANK (0x7F). +/// Validates a closed caption block pair for both CEA-608 and CEA-708 data. +/// +/// # Arguments +/// cc_block - A mutable slice containing exactly 3 bytes representing a CC block +/// +/// # Returns +/// true if the CC block is valid and should be processed +/// false if the CC block should be ignored +/// +/// # Behavior +/// 1. Header Validation: +/// - Checks the cc_valid flag (bit 2 of cc_block[0]). If 0, returns false immediately. +/// - extracts the cc_type (bits 0-1 of cc_block[0]). +/// +/// 2. CEA-708 (Type 2 or 3): +/// - No further validation is required beyond the cc_valid flag. Returns true. +/// +/// 3. CEA-608 (Type 0 or 1): +/// - Critical Parity Check: Validates parity for the second data byte (cc_block[2]). +/// If this fails, the entire pair is deemed corrupt, and the function returns false. +/// - Sanitization: Validates parity for the first data byte (cc_block[1]). +/// If this fails (but byte 2 was valid), cc_block[1] is overwritten with CC_SOLID_BLANK (0x7F). const CC_SOLID_BLANK: u8 = 0x7F; @@ -304,6 +304,13 @@ pub fn verify_parity(data: u8) -> bool { data.count_ones() & 1 == 1 } +/// Has different semantic meaning than just a solid blank. +/// 0x7F can be used as a parity mask to check if the 7 data bits are zero. (0x7F => 0111 1111). +/// Since the parity bit is forced to be 0 by the mask, it can no longer affect the result. +/// Therefore, the only way the total result can be 0 is if all the data bits (0-6) were originally zero. +/// This isn't related to the "solid blank" character - it's just that the mask happens to have the same value. +const PARITY_BIT_MASK: u8 = 0x7F; + /// Process CC data according to its type pub fn do_cb_dtvcc(ctx: &mut lib_cc_decode, dtvcc: &mut Dtvcc, cc_block: &[u8]) -> bool { let cc_valid = (cc_block[0] & 4) >> 2; @@ -313,8 +320,8 @@ pub fn do_cb_dtvcc(ctx: &mut lib_cc_decode, dtvcc: &mut Dtvcc, cc_block: &[u8]) if ctx.write_format != ccx_output_format::CCX_OF_DVDRAW && ctx.write_format != ccx_output_format::CCX_OF_RAW && (cc_block[0] == 0xFA || cc_block[0] == 0xFC || cc_block[0] == 0xFD) - && (cc_block[1] & CC_SOLID_BLANK) == 0 - && (cc_block[2] & CC_SOLID_BLANK) == 0 + && (cc_block[1] & PARITY_BIT_MASK) == 0 + && (cc_block[2] & PARITY_BIT_MASK) == 0 { return true; } From f5f47685037b7d7fe162b0317bba00b683dce6a0 Mon Sep 17 00:00:00 2001 From: ChubbyChipmunk77 Date: Mon, 29 Dec 2025 21:49:45 +0530 Subject: [PATCH 3/3] style: fix doc comment formatting for Clippy --- src/rust/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 0be5f2bf5..c9161e6db 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -273,7 +273,6 @@ extern "C" fn ccxr_process_cc_data( /// If this fails, the entire pair is deemed corrupt, and the function returns false. /// - Sanitization: Validates parity for the first data byte (cc_block[1]). /// If this fails (but byte 2 was valid), cc_block[1] is overwritten with CC_SOLID_BLANK (0x7F). - const CC_SOLID_BLANK: u8 = 0x7F; pub fn validate_cc_pair(cc_block: &mut [u8]) -> bool {