1use serde::{Deserialize, Serialize};
7
8use crate::types::{FlowControl, Parity};
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct SerialConfig {
13 pub port: String,
14 pub baud_rate: u32,
15 pub data_bits: u8,
16 pub parity: Parity,
17 pub stop_bits: u8,
18 pub flow_control: FlowControl,
19}
20
21impl Default for SerialConfig {
22 fn default() -> Self {
23 Self {
24 port: String::new(),
25 baud_rate: 9600,
26 data_bits: 8,
27 parity: Parity::None,
28 stop_bits: 1,
29 flow_control: FlowControl::None,
30 }
31 }
32}
33
34impl SerialConfig {
35 pub fn new() -> Self {
37 Self::default()
38 }
39
40 pub fn with_port(port: impl Into<String>) -> Self {
42 Self {
43 port: port.into(),
44 ..Default::default()
45 }
46 }
47
48 pub fn validate(&self) -> Result<(), String> {
50 if self.port.is_empty() {
51 return Err("Port cannot be empty".to_string());
52 }
53
54 if self.baud_rate == 0 {
55 return Err("Baud rate must be greater than 0".to_string());
56 }
57
58 if self.data_bits < 5 || self.data_bits > 8 {
59 return Err("Data bits must be between 5 and 8".to_string());
60 }
61
62 if self.stop_bits < 1 || self.stop_bits > 2 {
63 return Err("Stop bits must be 1 or 2".to_string());
64 }
65
66 Ok(())
67 }
68
69 pub fn format_display(&self) -> String {
71 let parity_char = match self.parity {
72 Parity::None => 'N',
73 Parity::Even => 'E',
74 Parity::Odd => 'O',
75 };
76
77 format!(
78 "{} @ {} bps, {}-{}-{}",
79 self.port, self.baud_rate, self.data_bits, parity_char, self.stop_bits
80 )
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_default_config() {
90 let config = SerialConfig::default();
91 assert_eq!(config.port, "");
92 assert_eq!(config.baud_rate, 9600);
93 assert_eq!(config.data_bits, 8);
94 assert_eq!(config.stop_bits, 1);
95 }
96
97 #[test]
98 fn test_with_port() {
99 let config = SerialConfig::with_port("/dev/ttyUSB0");
100 assert_eq!(config.port, "/dev/ttyUSB0");
101 assert_eq!(config.baud_rate, 9600);
102 }
103
104 #[test]
105 fn test_validate() {
106 let mut config = SerialConfig::default();
107 assert!(config.validate().is_err()); config.port = "/dev/ttyUSB0".to_string();
110 assert!(config.validate().is_ok());
111
112 config.baud_rate = 0;
113 assert!(config.validate().is_err());
114
115 config.baud_rate = 9600;
116 config.data_bits = 9;
117 assert!(config.validate().is_err());
118 }
119
120 #[test]
121 fn test_format_display() {
122 let config = SerialConfig {
123 port: "/dev/ttyUSB0".to_string(),
124 baud_rate: 115200,
125 data_bits: 8,
126 parity: Parity::None,
127 stop_bits: 1,
128 flow_control: FlowControl::None,
129 };
130
131 let display = config.format_display();
132 assert_eq!(display, "/dev/ttyUSB0 @ 115200 bps, 8-N-1");
133 }
134}