@@ -564,19 +564,58 @@ fn string_to_combo(arg: &str) -> Option<&str> {
564564}
565565
566566fn 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( "\t 115200\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