Skip to main content

async_serial/
lib.rs

1use std::{
2    io,
3    ops::{Deref, DerefMut},
4    os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd},
5};
6
7pub use async_io::Async;
8use async_io::IoSafe;
9pub use serialport::{SerialPortBuilder, new};
10pub mod error {
11    pub use serialport::{Error, Result};
12}
13
14pub type AsyncSerialPort = Async<
15    IoSafeAdapter<
16        cfg_select! {
17            unix => serialport::TTYPort,
18            windows => serialport::COMPort,
19        },
20    >,
21>;
22pub trait AsyncSerialPortBuilder {
23    fn open_async(self) -> serialport::Result<AsyncSerialPort>;
24}
25
26impl AsyncSerialPortBuilder for serialport::SerialPortBuilder {
27    fn open_async(self) -> serialport::Result<AsyncSerialPort> {
28        self.open_native()
29            .map(IoSafeAdapter)
30            .and_then(|io| Async::new(io).map_err(From::from))
31    }
32}
33
34/// An [`IoSafe`] newtype for [`serialport::SerialPort`] implementors, useful for [`Async`] wrapper.
35#[derive(Debug)]
36pub struct IoSafeAdapter<T>(T);
37
38impl<T> Deref for IoSafeAdapter<T> {
39    type Target = T;
40
41    fn deref(&self) -> &Self::Target {
42        &self.0
43    }
44}
45
46impl<T> DerefMut for IoSafeAdapter<T> {
47    fn deref_mut(&mut self) -> &mut Self::Target {
48        &mut self.0
49    }
50}
51
52impl<T: io::Read> io::Read for IoSafeAdapter<T> {
53    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
54        self.0.read(buf)
55    }
56}
57
58impl<T: io::Write> io::Write for IoSafeAdapter<T> {
59    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
60        self.0.write(buf)
61    }
62    fn flush(&mut self) -> io::Result<()> {
63        self.0.flush()
64    }
65}
66
67/// # Safety:
68/// The implementation of [`io::Read`] and [`io::Write`] for the wrapped serial port is [`IoSafe`]
69unsafe impl<T: io::Read + io::Write> IoSafe for IoSafeAdapter<T> {}
70
71impl<T: AsRawFd> AsRawFd for IoSafeAdapter<T> {
72    fn as_raw_fd(&self) -> RawFd {
73        self.0.as_raw_fd()
74    }
75}
76
77impl<T> AsFd for IoSafeAdapter<T>
78where
79    Self: AsRawFd,
80{
81    fn as_fd(&self) -> BorrowedFd<'_> {
82        // Safety: This fd lifespan is tied to the `T`
83        unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
84    }
85}