use std::time::Duration;
pub const DEFAULT_READ_TIMEOUT: Duration = Duration::from_millis(100);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DataBits {
Five,
Six,
Seven,
Eight,
}
impl DataBits {
#[must_use]
pub const fn bits(self) -> u8 {
match self {
Self::Five => 5,
Self::Six => 6,
Self::Seven => 7,
Self::Eight => 8,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StopBits {
One,
Two,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Parity {
None,
Even,
Odd,
Mark,
Space,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FlowControl {
None,
Hardware,
Software,
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct ModemStatus {
pub cts: bool,
pub dsr: bool,
pub ri: bool,
pub cd: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct ModemLineSnapshot {
pub dtr: bool,
pub rts: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SerialConfig {
pub baud_rate: u32,
pub data_bits: DataBits,
pub stop_bits: StopBits,
pub parity: Parity,
pub flow_control: FlowControl,
pub read_timeout: Duration,
}
impl Default for SerialConfig {
fn default() -> Self {
Self {
baud_rate: 115_200,
data_bits: DataBits::Eight,
stop_bits: StopBits::One,
parity: Parity::None,
flow_control: FlowControl::None,
read_timeout: DEFAULT_READ_TIMEOUT,
}
}
}
impl SerialConfig {
pub fn validate(&self) -> crate::Result<()> {
if self.baud_rate == 0 {
return Err(crate::Error::InvalidConfig(
"baud_rate must be non-zero".into(),
));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_115200_8n1_no_flow() {
let cfg = SerialConfig::default();
assert_eq!(cfg.baud_rate, 115_200);
assert_eq!(cfg.data_bits, DataBits::Eight);
assert_eq!(cfg.stop_bits, StopBits::One);
assert_eq!(cfg.parity, Parity::None);
assert_eq!(cfg.flow_control, FlowControl::None);
}
#[test]
fn data_bits_width_matches_enum() {
assert_eq!(DataBits::Five.bits(), 5);
assert_eq!(DataBits::Six.bits(), 6);
assert_eq!(DataBits::Seven.bits(), 7);
assert_eq!(DataBits::Eight.bits(), 8);
}
#[test]
fn validate_rejects_zero_baud() {
let cfg = SerialConfig {
baud_rate: 0,
..SerialConfig::default()
};
assert!(cfg.validate().is_err());
}
#[test]
fn validate_accepts_default() {
assert!(SerialConfig::default().validate().is_ok());
}
#[test]
fn modem_line_snapshot_default_both_false() {
let s = ModemLineSnapshot::default();
assert!(!s.dtr);
assert!(!s.rts);
}
}