#![cfg_attr(feature = "doc-cfg", feature(doc_cfg))]
#![warn(missing_docs)]
#![warn(private_interfaces)]
#![warn(private_bounds)]
use std::io::{IoSliceMut, IoSlice};
use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::task::Poll;
mod inner;
pub use serial2::{
COMMON_BAUD_RATES,
CharSize,
FlowControl,
IntoSettings,
KeepSettings,
Parity,
Settings,
StopBits,
TryFromError,
};
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "rs4xx")))]
#[cfg(any(feature = "doc", feature = "rs4xx"))]
pub use serial2::rs4xx;
use tokio::io::{AsyncRead, AsyncWrite};
pub struct SerialPort {
inner: inner::SerialPort,
}
impl SerialPort {
pub fn open(path: impl AsRef<Path>, settings: impl IntoSettings) -> std::io::Result<Self> {
let inner = serial2::SerialPort::open(path, settings)?;
let inner = inner::SerialPort::wrap(inner)?;
Ok(Self {
inner,
})
}
#[cfg(any(feature = "doc", all(unix, feature = "unix")))]
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "unix")))]
pub fn pair() -> std::io::Result<(Self, Self)> {
let (a, b) = serial2::SerialPort::pair()?;
let a = Self { inner: inner::SerialPort::wrap(a)? };
let b = Self { inner: inner::SerialPort::wrap(b)? };
Ok((a, b))
}
pub fn available_ports() -> std::io::Result<Vec<PathBuf>> {
serial2::SerialPort::available_ports()
}
pub fn set_configuration(&mut self, settings: &Settings) -> std::io::Result<()> {
self.inner.with_raw_mut(|raw| raw.set_configuration(settings))
}
pub fn get_configuration(&self) -> std::io::Result<Settings> {
self.inner.with_raw(|raw| raw.get_configuration())
}
pub fn try_clone(&self) -> std::io::Result<Self> {
let inner = self.inner.try_clone()?;
Ok(Self { inner })
}
#[cfg_attr(not(feature = "doc"), allow(rustdoc::broken_intra_doc_links))]
pub async fn read(&self, buf: &mut [u8]) -> std::io::Result<usize> {
self.inner.read(buf).await
}
pub async fn read_vectored(&self, buf: &mut [IoSliceMut<'_>]) -> std::io::Result<usize> {
self.inner.read_vectored(buf).await
}
pub fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}
#[cfg_attr(not(feature = "doc"), allow(rustdoc::broken_intra_doc_links))]
pub async fn write(&self, buf: &[u8]) -> std::io::Result<usize> {
self.inner.write(buf).await
}
#[cfg_attr(not(feature = "doc"), allow(rustdoc::broken_intra_doc_links))]
pub async fn write_all(&self, buf: &[u8]) -> std::io::Result<()> {
let mut written = 0;
while written < buf.len() {
written += self.write(&buf[written..]).await?;
}
Ok(())
}
#[cfg_attr(not(feature = "doc"), allow(rustdoc::broken_intra_doc_links))]
pub async fn write_vectored(&self, buf: &[IoSlice<'_>]) -> std::io::Result<usize> {
self.inner.write_vectored(buf).await
}
pub fn is_write_vectored(&self) -> bool {
self.inner.is_write_vectored()
}
pub fn discard_buffers(&self) -> std::io::Result<()> {
self.inner.with_raw(|raw| raw.discard_buffers())
}
pub fn discard_input_buffer(&self) -> std::io::Result<()> {
self.inner.with_raw(|raw| raw.discard_input_buffer())
}
pub fn discard_output_buffer(&self) -> std::io::Result<()> {
self.inner.with_raw(|raw| raw.discard_input_buffer())
}
pub fn set_rts(&self, state: bool) -> std::io::Result<()> {
self.inner.with_raw(|raw| raw.set_rts(state))
}
pub fn read_cts(&self) -> std::io::Result<bool> {
self.inner.with_raw(|raw| raw.read_cts())
}
pub fn set_dtr(&self, state: bool) -> std::io::Result<()> {
self.inner.with_raw(|raw| raw.set_dtr(state))
}
pub fn read_dsr(&self) -> std::io::Result<bool> {
self.inner.with_raw(|raw| raw.read_dsr())
}
pub fn read_ri(&self) -> std::io::Result<bool> {
self.inner.with_raw(|raw| raw.read_ri())
}
pub fn read_cd(&self) -> std::io::Result<bool> {
self.inner.with_raw(|raw| raw.read_cd())
}
pub fn set_break(&self, enable: bool) -> std::io::Result<()> {
self.inner.with_raw(|raw| raw.set_break(enable))
}
#[cfg(any(feature = "doc", all(feature = "rs4xx", target_os = "linux")))]
#[cfg_attr(feature = "doc-cfg", doc(cfg(all(feature = "rs4xx", target_os = "linux"))))]
pub fn get_rs4xx_mode(&self) -> std::io::Result<rs4xx::TransceiverMode> {
self.inner.with_raw(|raw| raw.get_rs4xx_mode())
}
#[cfg(any(feature = "doc", all(feature = "rs4xx", target_os = "linux")))]
#[cfg_attr(feature = "doc-cfg", doc(cfg(all(feature = "rs4xx", target_os = "linux"))))]
pub fn set_rs4xx_mode(&self, mode: impl Into<rs4xx::TransceiverMode>) -> std::io::Result<()> {
self.inner.with_raw(|raw| raw.set_rs4xx_mode(mode))
}
}
impl AsyncRead for SerialPort {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
self.get_mut().inner.poll_read(cx, buf)
}
}
impl AsyncWrite for SerialPort {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &[u8],
) -> Poll<std::io::Result<usize>> {
self.get_mut().inner.poll_write(cx, buf)
}
fn poll_write_vectored(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
bufs: &[IoSlice<'_>],
) -> Poll<Result<usize, std::io::Error>> {
self.get_mut().inner.poll_write_vectored(cx, bufs)
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut std::task::Context<'_>) -> Poll<Result<(), std::io::Error>> {
Poll::Ready(Ok(()))
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Result<(), std::io::Error>> {
self.get_mut().inner.poll_shutdown(cx)
}
}
impl std::fmt::Debug for SerialPort {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.inner, f)
}
}