Select Git revision
SkywardHub.pro
error.rs 5.38 KiB
use rustmex::{message::AdHoc, mxArray, FromMatlabError, MxArray};
/// Type alias for the result of the serialbridge functions
pub type SResult<T> = std::result::Result<T, Error>;
/// Utility trait to map errors to `rustmex::Error` more easily
pub trait MapMexError<T, E> {
/// Map the error to an ad-hoc error with the given `id` and `msg`
fn map_err_adhoc(self, id: &str, msg: &str) -> Result<T, rustmex::Error>;
/// Map the error to the given crate Error
fn mexerr(self, err: Error) -> Result<T, rustmex::Error>;
/// Map the error to the given function that returns a crate Error
fn map_mexerr<O>(self, err: O) -> Result<T, rustmex::Error>
where
O: FnOnce(E) -> Error;
}
impl<T, E> MapMexError<T, E> for Result<T, E> {
fn map_err_adhoc(self, id: &str, msg: &str) -> Result<T, rustmex::Error> {
Ok(self.map_err(|_| AdHoc(id, msg))?)
}
fn mexerr(self, err: Error) -> Result<T, rustmex::Error> {
self.map_err(|_| err.to_mexerr())
}
fn map_mexerr<O>(self, err: O) -> Result<T, rustmex::Error>
where
O: FnOnce(E) -> Error,
{
self.map_err(|e| err(e).to_mexerr())
}
}
impl<T> MapMexError<T, ()> for Option<T> {
fn map_err_adhoc(self, id: &str, msg: &str) -> Result<T, rustmex::Error> {
Ok(self.ok_or(AdHoc(id, msg))?)
}
fn mexerr(self, err: Error) -> Result<T, rustmex::Error> {
self.ok_or_else(|| err.to_mexerr())
}
fn map_mexerr<O>(self, err: O) -> Result<T, rustmex::Error>
where
O: FnOnce(()) -> Error,
{
self.ok_or_else(|| err(()).to_mexerr())
}
}
/// Error type for the serialbridge functions
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Too many parameters passed")]
TooManyParameters,
#[error("Missing serial mode (first argument)")]
MissingSerialMode,
#[error("Missing port name (second argument)")]
MissingPortName,
#[error("Missing port path (third argument)")]
MissingPortPath,
#[error("Missing baudrate (fourth argument)")]
MissingBaudrate,
#[error("Missing read amount (second argument)")]
MissingReadAmount,
#[error("Missing write data (second argument)")]
MissingWriteData,
#[error("String contains invalid characters")]
String(#[from] std::ffi::IntoStringError), #[error("Invalid Matlab type used, {0}")]
InvalidMatlabType(String),
#[error("Invalid serial mode (choose from 'Open', 'Close', 'Read', 'Write')")]
InvalidMode,
#[error("Invalid port name (2nd argument): {0}")]
InvalidPortName(Box<Self>),
#[error("Invalid port path (3rd argument): {0}")]
InvalidPortPath(Box<Self>),
#[error("Invalid baud rate (4th argument): {0}")]
InvalidBaudrate(Box<Self>),
#[error("Invalid read amount (2nd argument): {0}")]
InvalidReadAmount(Box<Self>),
#[error("Invalid write data (2nd argument): {0}")]
InvalidWriteData(Box<Self>),
#[error("Serial port error: {0}")]
SerialPort(#[from] serialport::Error),
#[error("I/O error: {0}")]
IO(#[from] std::io::Error),
#[error("Channel error: {0}")]
Channel(#[from] std::sync::mpsc::SendError<Vec<u8>>),
#[error("Parse error")]
Parse,
#[error("Matlab error: {0}")]
Matlab(#[from] rustmex::FromMatlabError<MxArray>),
#[error("{0}")]
Rustmex(#[from] rustmex::Error),
#[error("Return type cannot be assigned")]
ReturnType,
#[error("Serial port is not open")]
SerialNotOpen,
}
impl Error {
/// Get the error id (useful for `rustmex::Error` AdHoc Message construction)
fn id(&self) -> &str {
match self {
Error::TooManyParameters => "serialbridge:invalid_input",
Error::MissingSerialMode => "serialbridge:missing_input",
Error::MissingPortName => "serialbridge:missing_input",
Error::MissingPortPath => "serialbridge:missing_input",
Error::MissingBaudrate => "serialbridge:missing_input",
Error::MissingReadAmount => "serialbridge:missing_input",
Error::MissingWriteData => "serialbridge:missing_input",
Error::String(_) => "serialbridge:invalid_input",
Error::InvalidMatlabType(_) => "serialbridge:invalid_input",
Error::InvalidMode => "serialbridge:invalid_input",
Error::InvalidPortName(_) => "serialbridge:invalid_input",
Error::InvalidPortPath(_) => "serialbridge:invalid_input",
Error::InvalidBaudrate(_) => "serialbridge:invalid_input",
Error::InvalidReadAmount(_) => "serialbridge:invalid_input",
Error::InvalidWriteData(_) => "serialbridge:invalid_input",
Error::SerialPort(_) => "serialbridge:serial_error",
Error::IO(_) => "serialbridge:serial_error",
Error::Channel(_) => "serialbridge:channel_error",
Error::Parse => "serialbridge:parse_error",
Error::Matlab(_) => "serialbridge:matlab_error",
Error::Rustmex(err) => err.id(),
Error::ReturnType => "serialbridge:invalid_output",
Error::SerialNotOpen => "serialbridge:serial_error",
}
}
pub fn to_mexerr(&self) -> rustmex::Error {
AdHoc(self.id(), self.to_string()).into()
}
}
impl From<Error> for rustmex::Error {
fn from(err: Error) -> Self {
err.to_mexerr() }
}
impl From<FromMatlabError<&mxArray>> for Error {
fn from(err: FromMatlabError<&mxArray>) -> Self {
err.into()
}
}