macro_rules! impl_error_display {
(
$( <$($t:tt : $bound:path),+> )?
$name:path,
$self:ident =>
$display:literal
$(,
$($arg:expr),+
)?
) => {
impl$(<$($t : $bound),+>)? std::error::Error for $name {}
impl$(<$($t : $bound),+>)? std::fmt::Display for $name {
fn fmt(&$self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(
f,
$display
$(,
$($arg),+
)?
)
}
}
};
}
#[cfg(any(feature = "ascii", feature = "binary"))]
macro_rules! impl_is_timeout {
($name:ident) => {
paste::paste! {
impl $name {
#[doc = "[1]: " $name "::is_io"]
pub fn is_timeout(&self) -> bool {
matches!(self, $name::Io(e) if e.kind() == std::io::ErrorKind::TimedOut)
}
}
}
};
}
#[cfg(any(feature = "ascii", feature = "binary"))]
macro_rules! impl_is_io {
($name:ident) => {
impl $name {
pub fn is_io(&self) -> bool {
matches!(self, $name::Io(_))
}
}
};
}
#[cfg(any(feature = "ascii", feature = "binary"))]
macro_rules! impl_from_serialport_error {
($name:ident) => {
impl From<serialport::Error> for $name {
fn from(other: serialport::Error) -> Self {
use std::io;
match other.kind() {
serialport::ErrorKind::NoDevice => $name::SerialDeviceInUseOrDisconnected(
SerialDeviceInUseOrDisconnectedError(other.description.into_boxed_str()),
),
serialport::ErrorKind::InvalidInput => $name::Io(io::Error::new(
io::ErrorKind::InvalidInput,
other.description,
)),
serialport::ErrorKind::Unknown => {
$name::Io(io::Error::new(io::ErrorKind::Other, other.description))
}
serialport::ErrorKind::Io(kind) => {
$name::Io(io::Error::new(kind, other.description))
}
}
}
}
};
}
#[cfg(feature = "ascii")]
macro_rules! impl_from_ascii_check_error {
($name:ident {
$(
$from_variant:ident => $to_variant:ident
),+
$(,)?
}) => {
impl<R> From<AsciiCheckError<R>> for $name
where
R: SpecificResponse,
AnyResponse: From<R>,
{
fn from(other: AsciiCheckError<R>) -> Self {
match other {
$(
AsciiCheckError::$from_variant(e) => $name::$to_variant(e.into())
),+
}
}
}
impl From<AsciiCheckError<AnyResponse>> for $name {
fn from(other: AsciiCheckError<AnyResponse>) -> Self {
match other {
$(
AsciiCheckError::$from_variant(e) => $name::$to_variant(e)
),+
}
}
}
};
}
#[cfg(any(feature = "ascii", feature = "binary"))]
macro_rules! error_enum {
(
$(#[$attr:meta])*
pub enum $name:ident {
$(
$variant:ident($inner:path)
),+
$(,)?
}
$(
impl$(<$impl_t:ident $(: $impl_bound:path )? >)? From<$from_t:ident>
{
$($from_variant:ident => $to_variant:ident),+
$(,)?
}
)*
) => {
$(
#[$attr]
)*
#[allow(missing_docs)]
pub enum $name {
$(
$variant($inner )
),+
}
impl std::error::Error for $name {}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
$(
$name::$variant(e) => e.fmt(f)
),+
}
}
}
impl From<std::convert::Infallible> for $name {
fn from(_: std::convert::Infallible) -> Self {
unreachable!();
}
}
$(
impl From<$inner> for $name {
fn from(other: $inner) -> Self {
$name::$variant(other)
}
}
impl TryFrom<$name> for $inner {
type Error = $name;
fn try_from(other: $name) -> Result<Self, Self::Error> {
match other {
$name::$variant(value) => Ok(value),
value => Err(value)
}
}
}
)+
$(
impl From<$from_t> for $name {
fn from(other: $from_t) -> Self {
match other {
$($from_t::$from_variant(e) => $name::$to_variant(From::from(e))),+
}
}
}
impl TryFrom<$name> for $from_t {
type Error = $name;
fn try_from(other: $name) -> Result<Self, Self::Error> {
match other {
$(
$name::$to_variant(e) => Ok($from_t::$from_variant(From::from(e)))
),+
,
_ => Err(other)
}
}
}
)*
};
(
$(#[$attr:meta])*
pub enum $name:ident<$t:tt> {
$(
$variant:ident($inner:path)
),+
$(,)?
}
impl<$type:tt : $bound:tt>
) => {
$(
#[$attr]
)*
#[allow(missing_docs)]
pub enum $name<$t> {
$(
$variant($inner)
),+
}
impl<$type: $bound> std::error::Error for $name<$type> {}
impl<$type: $bound> std::fmt::Display for $name<$type> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
$(
$name::$variant(e) => e.fmt(f)
),+
}
}
}
impl<$type: $bound> From<std::convert::Infallible> for $name<$type> {
fn from(_: std::convert::Infallible) -> Self {
unreachable!();
}
}
$(
impl<$type: $bound> From<$inner> for $name<$type> {
fn from(other: $inner) -> Self {
$name::$variant(other)
}
}
impl<$type: $bound> TryFrom<$name<$type>> for $inner {
type Error = $name<$type>;
fn try_from(other: $name<$type>) -> Result<Self, Self::Error> {
match other {
$name::$variant(value) => Ok(value),
value => Err(value)
}
}
}
)+
};
}
#[cfg(feature = "ascii")]
mod ascii;
#[cfg(feature = "ascii")]
pub use ascii::*;
#[cfg(feature = "binary")]
mod binary;
#[cfg(feature = "binary")]
pub use binary::*;
#[cfg(all(feature = "ascii", feature = "binary"))]
mod all;
#[cfg(all(feature = "ascii", feature = "binary"))]
pub use all::*;
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct SerialDeviceInUseOrDisconnectedError(Box<str>);
impl_error_display! {
SerialDeviceInUseOrDisconnectedError,
self =>
"the specified device is either disconnected or already in use by another process: {}", self.0
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TryIntoSendError(());
impl TryIntoSendError {
pub(crate) fn new() -> Self {
TryIntoSendError(())
}
}
impl_error_display! {
TryIntoSendError,
self =>
"cannot convert the port into one that implements `Send`"
}