diff --git a/src/lib_ccx/utility.c b/src/lib_ccx/utility.c index 00f213414..ac5bfc878 100644 --- a/src/lib_ccx/utility.c +++ b/src/lib_ccx/utility.c @@ -8,7 +8,6 @@ int temp_debug = 0; // This is a convenience variable used to enable/disable debug on variable conditions. Find references to understand. volatile sig_atomic_t change_filename_requested = 0; - extern int ccxr_verify_crc32(uint8_t *buf, int len); extern int ccxr_levenshtein_dist(const uint64_t *s1, const uint64_t *s2, unsigned s1len, unsigned s2len); extern int ccxr_levenshtein_dist_char(const char *s1, const char *s2, unsigned s1len, unsigned s2len); @@ -269,6 +268,13 @@ void sleep_secs(int secs) #endif } +#ifndef DISABLE_RUST +extern int ccxr_hex_to_int(char high, char low); +int hex_to_int(char high, char low) +{ + return ccxr_hex_to_int(high, low); +} +#else int hex_to_int(char high, char low) { unsigned char h, l; @@ -286,6 +292,8 @@ int hex_to_int(char high, char low) return -1; return h * 16 + l; } +#endif + int hex_string_to_int(char *string, int len) { int total_return = 0; @@ -302,7 +310,6 @@ int hex_string_to_int(char *string, int len) } return total_return; } - #ifndef _WIN32 void m_signal(int sig, void (*func)(int)) { diff --git a/src/rust/lib_ccxr/src/util/hex.rs b/src/rust/lib_ccxr/src/util/hex.rs new file mode 100644 index 000000000..370e30947 --- /dev/null +++ b/src/rust/lib_ccxr/src/util/hex.rs @@ -0,0 +1,31 @@ +/// Converts a single lowercase hex character to its integer value. +/// Returns None if the character is not valid (0-9 or a-f). +fn hex_char_to_val(c: char) -> Option { + match c { + '0'..='9' => Some(c as i32 - '0' as i32), + 'a'..='f' => Some(c as i32 - 'a' as i32 + 10), + _ => None, + } +} + +/// Converts two lowercase hex characters into a combined integer value. +/// Returns None if either character is invalid. +pub fn hex_to_int(high: char, low: char) -> Option { + let h = hex_char_to_val(high)?; + let l = hex_char_to_val(low)?; + Some(h * 16 + l) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_hex_to_int() { + assert_eq!(hex_to_int('4', 'f'), Some(79)); + assert_eq!(hex_to_int('0', '0'), Some(0)); + assert_eq!(hex_to_int('f', 'f'), Some(255)); + assert_eq!(hex_to_int('z', '1'), None); // invalid + assert_eq!(hex_to_int('A', 'F'), None); // uppercase not supported + } +} diff --git a/src/rust/lib_ccxr/src/util/mod.rs b/src/rust/lib_ccxr/src/util/mod.rs index 2d05f1221..ef0e092fa 100644 --- a/src/rust/lib_ccxr/src/util/mod.rs +++ b/src/rust/lib_ccxr/src/util/mod.rs @@ -9,40 +9,29 @@ //! | `UNHAM_8_4` | [`decode_hamming_8_4`] | //! | `unham_24_18` | [`decode_hamming_24_18`] | //! | `levenshtein_dist`, levenshtein_dist_char` | [`levenshtein`](levenshtein()) | - pub mod bits; pub mod encoders_helper; pub mod encoding; +pub mod hex; pub mod levenshtein; pub mod log; pub mod time; - use std::os::raw::c_char; - -/// Helper function that converts a Rust-String (`string`) to C-String (`buffer`). -/// -/// # Safety -/// -/// `buffer` must have enough allocated space for `string` to fit. pub fn write_string_into_pointer(buffer: *mut c_char, string: &str) { let buffer = unsafe { std::slice::from_raw_parts_mut(buffer as *mut u8, string.len() + 1) }; buffer[..string.len()].copy_from_slice(string.as_bytes()); buffer[string.len()] = b'\0'; } - #[cfg(test)] mod tests { use super::*; - #[test] fn test_write_string_into_pointer() { let test_string = "CCExtractor is the best"; let mut buffer = vec![0u8; test_string.len() + 1]; let buffer_ptr = buffer.as_mut_ptr() as *mut c_char; - write_string_into_pointer(buffer_ptr, test_string); - assert_eq!(&buffer[..test_string.len()], test_string.as_bytes()); - assert_eq!(buffer[test_string.len()], 0); // Check null terminator + assert_eq!(buffer[test_string.len()], 0); } } diff --git a/src/rust/src/libccxr_exports/mod.rs b/src/rust/src/libccxr_exports/mod.rs index f5016a95b..aebaf5210 100644 --- a/src/rust/src/libccxr_exports/mod.rs +++ b/src/rust/src/libccxr_exports/mod.rs @@ -5,6 +5,7 @@ pub mod demuxer; pub mod demuxerdata; pub mod net; pub mod time; +pub mod util; use crate::ccx_options; use lib_ccxr::util::log::*; use lib_ccxr::util::{bits::*, levenshtein::*}; diff --git a/src/rust/src/libccxr_exports/util.rs b/src/rust/src/libccxr_exports/util.rs new file mode 100644 index 000000000..e6734f9e7 --- /dev/null +++ b/src/rust/src/libccxr_exports/util.rs @@ -0,0 +1,12 @@ +use std::ffi::{c_char, c_int}; + +/// Rust equivalent for `hex_to_int` function in C. Uses C-native types as input and output. +/// +/// # Safety +/// +/// `high` and `low` must be valid ASCII characters. Invalid characters will +/// return -1 rather than causing undefined behavior. +#[no_mangle] +pub unsafe extern "C" fn ccxr_hex_to_int(high: c_char, low: c_char) -> c_int { + lib_ccxr::util::hex::hex_to_int(high as u8 as char, low as u8 as char).unwrap_or(-1) +}