Skip to content

Commit d71ecd4

Browse files
committed
Adding fix for parsing the baud values
1 parent 86bc17e commit d71ecd4

File tree

1 file changed

+109
-13
lines changed

1 file changed

+109
-13
lines changed

src/uu/stty/src/stty.rs

Lines changed: 109 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -564,19 +564,58 @@ fn string_to_combo(arg: &str) -> Option<&str> {
564564
}
565565

566566
fn string_to_baud(arg: &str) -> Option<AllFlags<'_>> {
567-
// BSDs use a u32 for the baud rate, so any decimal number applies.
568-
#[cfg(any(
569-
target_os = "freebsd",
570-
target_os = "dragonfly",
571-
target_os = "ios",
572-
target_os = "macos",
573-
target_os = "netbsd",
574-
target_os = "openbsd"
575-
))]
576-
if let Ok(n) = arg.parse::<u32>() {
577-
return Some(AllFlags::Baud(n));
567+
// Normalize the input: trim whitespace and leading '+'
568+
let normalized = arg.trim().trim_start_matches('+');
569+
570+
// Try to parse as a floating point number for rounding
571+
if let Ok(f) = normalized.parse::<f64>() {
572+
let rounded = f.round() as u32;
573+
574+
// BSDs use a u32 for the baud rate, so any decimal number applies.
575+
#[cfg(any(
576+
target_os = "freebsd",
577+
target_os = "dragonfly",
578+
target_os = "ios",
579+
target_os = "macos",
580+
target_os = "netbsd",
581+
target_os = "openbsd"
582+
))]
583+
return Some(AllFlags::Baud(rounded));
584+
585+
// On other platforms, find the closest valid baud rate
586+
#[cfg(not(any(
587+
target_os = "freebsd",
588+
target_os = "dragonfly",
589+
target_os = "ios",
590+
target_os = "macos",
591+
target_os = "netbsd",
592+
target_os = "openbsd"
593+
)))]
594+
{
595+
let rounded_str = rounded.to_string();
596+
// First try exact match
597+
for (text, baud_rate) in BAUD_RATES {
598+
if *text == rounded_str {
599+
return Some(AllFlags::Baud(*baud_rate));
600+
}
601+
}
602+
// If no exact match, find closest baud rate
603+
let mut closest: Option<(u32, nix::sys::termios::BaudRate)> = None;
604+
for (text, baud_rate) in BAUD_RATES {
605+
if let Ok(rate_val) = text.parse::<u32>() {
606+
let diff = rate_val.abs_diff(rounded);
607+
if closest.is_none() || diff < closest.unwrap().0 {
608+
closest = Some((diff, *baud_rate));
609+
}
610+
}
611+
}
612+
if let Some((_, baud_rate)) = closest {
613+
return Some(AllFlags::Baud(baud_rate));
614+
}
615+
}
578616
}
579-
617+
618+
// Fallback: try exact string match for non-numeric baud rate names
580619
#[cfg(not(any(
581620
target_os = "freebsd",
582621
target_os = "dragonfly",
@@ -586,10 +625,11 @@ fn string_to_baud(arg: &str) -> Option<AllFlags<'_>> {
586625
target_os = "openbsd"
587626
)))]
588627
for (text, baud_rate) in BAUD_RATES {
589-
if *text == arg {
628+
if *text == normalized {
590629
return Some(AllFlags::Baud(*baud_rate));
591630
}
592631
}
632+
593633
None
594634
}
595635

@@ -1082,3 +1122,59 @@ impl TermiosFlag for LocalFlags {
10821122
termios.local_flags.set(*self, val);
10831123
}
10841124
}
1125+
1126+
#[cfg(test)]
1127+
mod tests {
1128+
use super::*;
1129+
1130+
#[test]
1131+
fn test_string_to_baud_exact_match() {
1132+
assert!(string_to_baud("9600").is_some());
1133+
assert!(string_to_baud("115200").is_some());
1134+
}
1135+
1136+
#[test]
1137+
fn test_string_to_baud_with_whitespace() {
1138+
assert!(string_to_baud(" 9600 ").is_some());
1139+
assert!(string_to_baud("\t115200\n").is_some());
1140+
}
1141+
1142+
#[test]
1143+
fn test_string_to_baud_with_plus_sign() {
1144+
assert!(string_to_baud("+9600").is_some());
1145+
assert!(string_to_baud(" +115200 ").is_some());
1146+
}
1147+
1148+
#[test]
1149+
fn test_string_to_baud_with_decimal() {
1150+
assert!(string_to_baud("9600.0").is_some());
1151+
assert!(string_to_baud("9600.4").is_some());
1152+
}
1153+
1154+
#[test]
1155+
fn test_string_to_baud_rounding() {
1156+
assert!(string_to_baud("9600.5").is_some());
1157+
assert!(string_to_baud("9599.6").is_some());
1158+
}
1159+
1160+
#[cfg(not(any(
1161+
target_os = "freebsd",
1162+
target_os = "dragonfly",
1163+
target_os = "ios",
1164+
target_os = "macos",
1165+
target_os = "netbsd",
1166+
target_os = "openbsd"
1167+
)))]
1168+
#[test]
1169+
fn test_string_to_baud_closest_match() {
1170+
assert!(string_to_baud("9601").is_some());
1171+
assert!(string_to_baud("115000").is_some());
1172+
}
1173+
1174+
#[test]
1175+
fn test_string_to_baud_invalid() {
1176+
assert!(string_to_baud("invalid").is_none());
1177+
assert!(string_to_baud("").is_none());
1178+
assert!(string_to_baud("abc123").is_none());
1179+
}
1180+
}

0 commit comments

Comments
 (0)