pub(crate) fn parse_bytes<T: std::str::FromStr>(b: &[u8]) -> Option<T> {
std::str::from_utf8(b).ok()?.parse().ok()
}
pub(crate) fn trim_spaces_end(v: &mut Vec<u8>) {
while v.last() == Some(&b' ') {
v.pop();
}
}
pub(crate) fn extract_frequency_mhz(comment: &[u8]) -> Option<f32> {
let mhz_pos = comment.windows(3).position(|w| w == b"MHz")?;
if mhz_pos == 0 {
return None; }
let num_bytes = &comment[..mhz_pos];
let trimmed = num_bytes.iter()
.position(|&b| b != b' ')
.map(|i| &num_bytes[i..])
.unwrap_or(num_bytes);
if trimmed.is_empty() {
return None;
}
if !trimmed.iter().all(|&b| b.is_ascii_digit() || b == b'.') {
return None;
}
std::str::from_utf8(trimmed).ok()?.parse().ok()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn frequency_basic() {
assert_eq!(extract_frequency_mhz(b"146.520MHz T100 comment"), Some(146.52));
}
#[test]
fn frequency_no_decimal() {
assert_eq!(extract_frequency_mhz(b"146MHz comment"), Some(146.0));
}
#[test]
fn frequency_not_at_start() {
assert_eq!(extract_frequency_mhz(b"comment 146.520MHz"), None);
}
#[test]
fn frequency_absent() {
assert_eq!(extract_frequency_mhz(b"no frequency here"), None);
}
}