use crate::{ClearBuffer, DataBits, FlowControl, Parity, Serial, SerialPort, StopBits};
use futures::ready;
use serialport::SerialPortBuilder;
use std::io::{self, Read, Write};
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;
use tokio::io::unix::AsyncFd;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
pub struct AsyncSerial {
io: AsyncFd<Serial>,
}
impl AsyncSerial {
pub fn from_builder(builder: &SerialPortBuilder) -> io::Result<AsyncSerial> {
let serial = Serial::from_builder(builder)?;
let io = AsyncFd::new(serial)?;
Ok(AsyncSerial { io })
}
pub fn pair() -> crate::Result<(Self, Self)> {
let (master, slave) = Serial::pair()?;
let master = AsyncSerial {
io: AsyncFd::new(master)?,
};
let slave = AsyncSerial {
io: AsyncFd::new(slave)?,
};
Ok((master, slave))
}
pub fn set_exclusive(&mut self, exclusive: bool) -> crate::Result<()> {
self.io.get_mut().set_exclusive(exclusive)
}
pub fn exclusive(&self) -> bool {
self.io.get_ref().exclusive()
}
}
impl SerialPort for AsyncSerial {
fn name(&self) -> Option<String> {
self.io.get_ref().name()
}
fn baud_rate(&self) -> crate::Result<u32> {
self.io.get_ref().baud_rate()
}
fn data_bits(&self) -> crate::Result<DataBits> {
self.io.get_ref().data_bits()
}
fn flow_control(&self) -> crate::Result<FlowControl> {
self.io.get_ref().flow_control()
}
fn parity(&self) -> crate::Result<Parity> {
self.io.get_ref().parity()
}
fn stop_bits(&self) -> crate::Result<StopBits> {
self.io.get_ref().stop_bits()
}
fn timeout(&self) -> Duration {
Duration::from_secs(0)
}
fn set_baud_rate(&mut self, baud_rate: u32) -> crate::Result<()> {
self.io.get_mut().set_baud_rate(baud_rate)
}
fn set_data_bits(&mut self, data_bits: DataBits) -> crate::Result<()> {
self.io.get_mut().set_data_bits(data_bits)
}
fn set_flow_control(&mut self, flow_control: FlowControl) -> crate::Result<()> {
self.io.get_mut().set_flow_control(flow_control)
}
fn set_parity(&mut self, parity: Parity) -> crate::Result<()> {
self.io.get_mut().set_parity(parity)
}
fn set_stop_bits(&mut self, stop_bits: StopBits) -> crate::Result<()> {
self.io.get_mut().set_stop_bits(stop_bits)
}
fn set_timeout(&mut self, _: Duration) -> crate::Result<()> {
Ok(())
}
fn write_request_to_send(&mut self, level: bool) -> crate::Result<()> {
self.io.get_mut().write_request_to_send(level)
}
fn write_data_terminal_ready(&mut self, level: bool) -> crate::Result<()> {
self.io.get_mut().write_data_terminal_ready(level)
}
fn read_clear_to_send(&mut self) -> crate::Result<bool> {
self.io.get_mut().read_clear_to_send()
}
fn read_data_set_ready(&mut self) -> crate::Result<bool> {
self.io.get_mut().read_data_set_ready()
}
fn read_ring_indicator(&mut self) -> crate::Result<bool> {
self.io.get_mut().read_ring_indicator()
}
fn read_carrier_detect(&mut self) -> crate::Result<bool> {
self.io.get_mut().read_carrier_detect()
}
fn bytes_to_read(&self) -> crate::Result<u32> {
self.io.get_ref().bytes_to_read()
}
fn bytes_to_write(&self) -> crate::Result<u32> {
self.io.get_ref().bytes_to_write()
}
fn clear(&self, buffer_to_clear: ClearBuffer) -> crate::Result<()> {
self.io.get_ref().clear(buffer_to_clear)
}
fn try_clone(&self) -> crate::Result<Box<dyn SerialPort>> {
self.io.get_ref().try_clone()
}
fn set_break(&self) -> crate::Result<()> {
self.io.get_ref().set_break()
}
fn clear_break(&self) -> crate::Result<()> {
self.io.get_ref().clear_break()
}
}
impl Read for AsyncSerial {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.io.get_mut().read(buf)
}
}
impl Write for AsyncSerial {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.io.get_mut().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.io.get_mut().flush()
}
}
use std::os::unix::io::{AsRawFd, RawFd};
impl AsRawFd for AsyncSerial {
fn as_raw_fd(&self) -> RawFd {
self.io.as_raw_fd()
}
}
impl AsyncRead for AsyncSerial {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
loop {
let mut guard = ready!(self.io.poll_read_ready(cx))?;
match guard.try_io(|_| {
let read = self.io.get_ref().read(buf.initialize_unfilled())?;
buf.advance(read);
Ok(())
}) {
Ok(result) => return Poll::Ready(result),
Err(_would_block) => continue,
}
}
}
}
impl AsyncWrite for AsyncSerial {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
loop {
let mut guard = ready!(self.io.poll_write_ready(cx))?;
match guard.try_io(|_| self.io.get_ref().write(buf)) {
Ok(x) => return Poll::Ready(x),
Err(_would_block) => continue,
}
}
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
loop {
let mut guard = ready!(self.io.poll_write_ready(cx))?;
match guard.try_io(|_| self.io.get_ref().flush()) {
Ok(x) => return Poll::Ready(x),
Err(_would_block) => continue,
}
}
}
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
}