1#[cfg(doctest)]
66#[doc = include_str!("../README.md")]
67struct ReadMe;
68
69use std::{
70 io,
71 sync::{Arc, Mutex},
72 time::Duration,
73};
74
75use rand::Rng;
76
77use serialport::{ClearBuffer, DataBits, FlowControl, Parity, Result, SerialPort, StopBits};
78
79use mockpipe::MockPipe;
80
81struct Config {
82 baud_rate: u32,
84
85 data_bits: DataBits,
87
88 flow_control: FlowControl,
90
91 parity: Parity,
93
94 stop_bits: StopBits,
96
97 simulate_delay: bool,
105
106 noise_on_config_mismatch: bool,
108}
109
110impl Config {
111 fn new(baud_rate: u32) -> Self {
112 Self {
113 baud_rate,
114 data_bits: DataBits::Eight,
115 flow_control: FlowControl::None,
116 parity: Parity::None,
117 stop_bits: StopBits::One,
118 simulate_delay: false,
119 noise_on_config_mismatch: false,
120 }
121 }
122
123 fn bits_per_byte(&self) -> u32 {
130 1 + match self.data_bits {
132 DataBits::Five => 5,
133 DataBits::Six => 6,
134 DataBits::Seven => 7,
135 DataBits::Eight => 8,
136 } + match self.parity {
137 Parity::Odd | Parity::Even => 1,
138 Parity::None => 0,
139 } + match self.stop_bits {
140 StopBits::One => 1,
141 StopBits::Two => 2,
142 }
143 }
144
145 fn byte_duration(&self) -> Option<Duration> {
147 self.simulate_delay.then(|| {
148 Duration::from_micros(((1_000_000 / self.baud_rate) * self.bits_per_byte()) as u64)
149 })
150 }
151
152 fn physical_settings_mismatch(&self, other: &Config) -> bool {
155 self.baud_rate != other.baud_rate
156 || self.data_bits != other.data_bits
157 || self.parity != other.parity
158 || self.stop_bits != other.stop_bits
159 }
160}
161
162#[derive(Clone)]
181pub struct VirtualPort {
182 config: Arc<Mutex<Config>>,
184
185 paired_port_config: Option<Arc<Mutex<Config>>>,
187
188 pipe: MockPipe,
189
190 rts: Arc<Mutex<bool>>,
193 cts: Arc<Mutex<bool>>,
194 dtr: Arc<Mutex<bool>>,
195 dsr_cd: Arc<Mutex<bool>>,
196}
197
198impl VirtualPort {
199 pub fn loopback(baud_rate: u32, buffer_capacity: u32) -> Result<Self> {
201 let rts_cts = Arc::new(Mutex::new(true));
202 let dtr_dsr_cd = Arc::new(Mutex::new(true));
203
204 Ok(Self {
205 config: Arc::new(Mutex::new(Config::new(baud_rate))),
206 paired_port_config: None,
207
208 pipe: MockPipe::loopback(buffer_capacity as usize),
209
210 rts: rts_cts.clone(),
211 cts: rts_cts.clone(),
212 dtr: dtr_dsr_cd.clone(),
213 dsr_cd: dtr_dsr_cd.clone(),
214 })
215 }
216
217 pub fn pair(baud_rate: u32, buffer_capacity: u32) -> Result<(Self, Self)> {
220 let config1 = Arc::new(Mutex::new(Config::new(baud_rate)));
221 let config2 = Arc::new(Mutex::new(Config::new(baud_rate)));
222
223 let (pipe1, pipe2) = MockPipe::pair(buffer_capacity as usize);
224
225 let rts = Arc::new(Mutex::new(true));
226 let cts = Arc::new(Mutex::new(true));
227 let dtr = Arc::new(Mutex::new(true));
228 let dsr_cd = Arc::new(Mutex::new(true));
229
230 let port1 = Self {
231 config: config1.clone(),
232 paired_port_config: Some(config2.clone()),
233
234 pipe: pipe1,
235
236 rts: rts.clone(),
237 cts: cts.clone(),
238 dtr: dtr.clone(),
239 dsr_cd: dsr_cd.clone(),
240 };
241
242 let port2 = Self {
243 config: config2,
244 paired_port_config: Some(config1),
245
246 pipe: pipe2,
247
248 rts: cts.clone(),
249 cts: rts.clone(),
250 dtr: dsr_cd.clone(),
251 dsr_cd: dtr.clone(),
252 };
253
254 Ok((port1, port2))
255 }
256
257 pub fn into_boxed(self) -> Box<dyn SerialPort> {
259 Box::new(self)
260 }
261
262 pub fn simulate_delay(&self) -> bool {
264 self.config.lock().unwrap().simulate_delay
265 }
266
267 pub fn set_simulate_delay(&mut self, value: bool) {
269 self.config.lock().unwrap().simulate_delay = value;
270 }
271
272 pub fn noise_on_config_mismatch(&self) -> bool {
274 self.config.lock().unwrap().noise_on_config_mismatch
275 }
276
277 pub fn set_noise_on_config_mismatch(&mut self, value: bool) {
279 self.config.lock().unwrap().noise_on_config_mismatch = value;
280 }
281}
282
283impl io::Read for VirtualPort {
284 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
285 let bytes_to_read = self.pipe.read(buf)?;
286
287 let (noise_required, delay_per_byte) = {
289 let config = self.config.lock().unwrap();
290
291 let noise_required = if config.noise_on_config_mismatch {
293 if let Some(paired_port_config) = &self.paired_port_config {
294 let paired_config = paired_port_config.lock().unwrap();
295 config.physical_settings_mismatch(&paired_config)
296 } else {
297 false
298 }
299 } else {
300 false
301 };
302
303 let delay_per_byte = config.byte_duration();
305
306 (noise_required, delay_per_byte)
307 };
308
309 if noise_required {
311 let mut rng = rand::thread_rng();
312 buf.iter_mut()
313 .take(bytes_to_read)
314 .for_each(|byte| *byte = rng.gen());
315 }
316
317 if let Some(delay) = delay_per_byte {
319 std::thread::sleep(delay * bytes_to_read as u32);
320 }
321
322 Ok(bytes_to_read)
323 }
324}
325
326impl io::Write for VirtualPort {
327 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
328 self.pipe.write(buf)
329 }
330
331 fn flush(&mut self) -> io::Result<()> {
332 self.pipe.flush()
333 }
334}
335
336impl SerialPort for VirtualPort {
337 fn name(&self) -> Option<String> {
338 None
339 }
340
341 fn baud_rate(&self) -> Result<u32> {
342 Ok(self.config.lock().unwrap().baud_rate)
343 }
344
345 fn data_bits(&self) -> Result<DataBits> {
346 Ok(self.config.lock().unwrap().data_bits)
347 }
348
349 fn flow_control(&self) -> Result<FlowControl> {
350 Ok(self.config.lock().unwrap().flow_control)
351 }
352
353 fn parity(&self) -> Result<Parity> {
354 Ok(self.config.lock().unwrap().parity)
355 }
356
357 fn stop_bits(&self) -> Result<StopBits> {
358 Ok(self.config.lock().unwrap().stop_bits)
359 }
360
361 fn timeout(&self) -> Duration {
362 self.pipe.timeout().unwrap_or(Duration::MAX)
363 }
364
365 fn set_baud_rate(&mut self, baud_rate: u32) -> Result<()> {
366 self.config.lock().unwrap().baud_rate = baud_rate;
367 Ok(())
368 }
369
370 fn set_flow_control(&mut self, flow_control: FlowControl) -> Result<()> {
371 self.config.lock().unwrap().flow_control = flow_control;
372 Ok(())
373 }
374
375 fn set_parity(&mut self, parity: Parity) -> Result<()> {
376 self.config.lock().unwrap().parity = parity;
377 Ok(())
378 }
379
380 fn set_data_bits(&mut self, data_bits: DataBits) -> Result<()> {
381 self.config.lock().unwrap().data_bits = data_bits;
382 Ok(())
383 }
384
385 fn set_stop_bits(&mut self, stop_bits: StopBits) -> Result<()> {
386 self.config.lock().unwrap().stop_bits = stop_bits;
387 Ok(())
388 }
389
390 fn set_timeout(&mut self, timeout: Duration) -> Result<()> {
391 self.pipe.set_timeout(match timeout {
392 Duration::MAX => None,
393 duration => Some(duration),
394 });
395 Ok(())
396 }
397
398 fn write_request_to_send(&mut self, level: bool) -> Result<()> {
399 *self.rts.lock().unwrap() = level;
400 Ok(())
401 }
402
403 fn write_data_terminal_ready(&mut self, level: bool) -> Result<()> {
404 *self.dtr.lock().unwrap() = level;
405 Ok(())
406 }
407
408 fn read_clear_to_send(&mut self) -> Result<bool> {
409 Ok(*self.cts.lock().unwrap())
410 }
411
412 fn read_data_set_ready(&mut self) -> Result<bool> {
413 Ok(*self.dsr_cd.lock().unwrap())
414 }
415
416 fn read_ring_indicator(&mut self) -> Result<bool> {
417 Ok(false)
418 }
419
420 fn read_carrier_detect(&mut self) -> Result<bool> {
421 Ok(*self.dsr_cd.lock().unwrap())
422 }
423
424 fn bytes_to_read(&self) -> Result<u32> {
425 Ok(u32::try_from(self.pipe.read_buffer_len()).unwrap())
429 }
430
431 fn bytes_to_write(&self) -> Result<u32> {
432 Ok(u32::try_from(self.pipe.write_buffer_len()).unwrap())
434 }
435
436 fn clear(&self, buffer_to_clear: ClearBuffer) -> Result<()> {
437 match buffer_to_clear {
438 ClearBuffer::Input => self.pipe.clear_read(),
439 ClearBuffer::Output => self.pipe.clear_write(),
440 ClearBuffer::All => self.pipe.clear(),
441 }
442 Ok(())
443 }
444
445 fn try_clone(&self) -> Result<Box<dyn SerialPort>> {
446 Ok(Box::new(self.clone()))
447 }
448
449 fn set_break(&self) -> Result<()> {
450 Ok(())
451 }
452
453 fn clear_break(&self) -> Result<()> {
454 Ok(())
455 }
456}
457
458#[cfg(test)]
459mod tests {
460 use std::io::{Read, Write};
461
462 use super::*;
463
464 #[test]
465 fn test_control_lines() {
466 let mut port = VirtualPort::loopback(9600, 1024).unwrap();
467
468 port.write_request_to_send(true).unwrap();
469 assert!(port.read_clear_to_send().unwrap());
470
471 port.write_data_terminal_ready(true).unwrap();
472 assert!(port.read_data_set_ready().unwrap());
473
474 port.write_request_to_send(false).unwrap();
475 assert!(!port.read_clear_to_send().unwrap());
476
477 port.write_data_terminal_ready(false).unwrap();
478 assert!(!port.read_data_set_ready().unwrap());
479 }
480
481 #[test]
482 fn test_buffer_clearing() {
483 let mut port = VirtualPort::loopback(9600, 1024).unwrap();
484 port.set_timeout(Duration::from_millis(100)).unwrap();
485 let write_data = b"test";
486 let mut read_data = [0u8; 4];
487
488 port.write_all(write_data).unwrap();
489 port.clear(ClearBuffer::All).unwrap();
490
491 assert_eq!(
492 port.read_exact(&mut read_data).unwrap_err().kind(),
493 io::ErrorKind::TimedOut
494 );
495 }
496
497 #[test]
498 fn test_clone() {
499 let port = VirtualPort::loopback(9600, 1024).unwrap();
500 let port_clone = port.try_clone().unwrap();
501
502 assert_eq!(port.baud_rate().unwrap(), port_clone.baud_rate().unwrap());
503 }
504
505 #[test]
506 fn test_config_change() {
507 let mut port = VirtualPort::loopback(9600, 1024).unwrap();
508
509 port.set_baud_rate(19200).unwrap();
510 assert_eq!(port.baud_rate().unwrap(), 19200);
511
512 port.set_data_bits(DataBits::Seven).unwrap();
513 assert_eq!(port.data_bits().unwrap(), DataBits::Seven);
514
515 port.set_flow_control(FlowControl::Software).unwrap();
516 assert_eq!(port.flow_control().unwrap(), FlowControl::Software);
517
518 port.set_parity(Parity::Odd).unwrap();
519 assert_eq!(port.parity().unwrap(), Parity::Odd);
520
521 port.set_stop_bits(StopBits::Two).unwrap();
522 assert_eq!(port.stop_bits().unwrap(), StopBits::Two);
523 }
524
525 #[test]
526 fn test_delay_simulation() {
527 use std::time::Instant;
528
529 let mut port = VirtualPort::loopback(50, 1024).unwrap();
530
531 assert!(!port.simulate_delay());
533
534 port.set_simulate_delay(true);
536 assert!(port.simulate_delay());
537
538 let write_data = b"hello";
541 port.write_all(write_data).unwrap();
542
543 let mut read_data = [0u8; 5];
545 let start = Instant::now();
546 port.read_exact(&mut read_data).unwrap();
547 let duration = start.elapsed();
548
549 assert_eq!(&read_data, write_data);
550 assert!(duration.as_millis() > 700);
551 }
552
553 #[test]
554 fn test_noise_on_config_mismatch() {
555 let (mut port1, mut port2) = VirtualPort::pair(9600, 1024).unwrap();
556
557 assert!(!port1.noise_on_config_mismatch());
559 assert!(!port2.noise_on_config_mismatch());
560
561 let write_data = b"hello world";
562 let mut read_data = [0u8; 11];
563
564 port1.write_all(write_data).unwrap();
568
569 read_data.fill(0);
571 port2.read_exact(&mut read_data).unwrap();
572
573 assert_eq!(&read_data, write_data);
575
576 port2.set_baud_rate(19200).unwrap();
580
581 port1.write_all(write_data).unwrap();
583
584 read_data.fill(0);
586 port2.read_exact(&mut read_data).unwrap();
587
588 assert_eq!(&read_data, write_data);
590
591 port2.set_noise_on_config_mismatch(true);
595 assert!(!port1.noise_on_config_mismatch());
596 assert!(port2.noise_on_config_mismatch());
597
598 port2.set_baud_rate(port1.baud_rate().unwrap()).unwrap();
600
601 port1.write_all(write_data).unwrap();
603
604 read_data.fill(0);
606 port2.read_exact(&mut read_data).unwrap();
607
608 assert_eq!(&read_data, write_data);
610
611 port2.set_baud_rate(19200).unwrap();
615
616 port1.write_all(write_data).unwrap();
618
619 read_data.fill(0);
621 port2.read_exact(&mut read_data).unwrap();
622
623 assert_ne!(&read_data, write_data);
625 assert!(read_data.iter().any(|&byte| byte != 0));
626 }
627}