From ab576bf6d3e339302d86101317b978268f78cfcb Mon Sep 17 00:00:00 2001 From: Federico Lolli <federico.lolli@skywarder.eu> Date: Sat, 24 Feb 2024 15:43:01 +0100 Subject: [PATCH] Update msg errors More comprehensive message errors introduced --- src/error.rs | 9 +++++++++ src/lib.rs | 11 ++++++++--- src/serial.rs | 21 ++++++++++++++++++++- src/types.rs | 10 ++++++---- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/error.rs b/src/error.rs index c6f8e9b..f9b35db 100644 --- a/src/error.rs +++ b/src/error.rs @@ -86,6 +86,13 @@ pub enum Error { SerialPort(#[from] serialport::Error), #[error("I/O error: {0}")] IO(#[from] std::io::Error), + #[error("No data available to read from serial (or timeout too short)")] + NoDataAvailable, + #[error("Incomplete read: {amount_read} bytes read. {inner}")] + IncompleteRead { + amount_read: usize, + inner: Box<Self>, + }, #[error("Channel error: {0}")] Channel(#[from] std::sync::mpsc::SendError<Vec<u8>>), #[error("Parse error")] @@ -121,6 +128,8 @@ impl Error { Error::InvalidWriteData(_) => "serialbridge:invalid_input", Error::SerialPort(_) => "serialbridge:serial_error", Error::IO(_) => "serialbridge:serial_error", + Error::NoDataAvailable => "serialbridge:serial_error", + Error::IncompleteRead { .. } => "serialbridge:serial_error", Error::Channel(_) => "serialbridge:channel_error", Error::Parse => "serialbridge:parse_error", Error::Matlab(_) => "serialbridge:matlab_error", diff --git a/src/lib.rs b/src/lib.rs index 2e2dd29..4ef314a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -146,15 +146,20 @@ fn read_from_serial(mut outputs: Output<'_>, args: Args<'_>) -> SResult<()> { Error::InvalidMatlabType("do not use decimal units, use a positive integer".into()), ))); } - let n_doubles = arg as usize; + let n_singles = arg as usize; // Read n_doubles from the serial port - let bytes = SERIAL.read().read_n_bytes(&port, n_doubles * 4)?; + let n_bytes = n_singles * 4; + let bytes = SERIAL.read().read_n_bytes(&port, n_bytes)?; let doubles = bytes .chunks_exact(4) .map(|chunk| f32::from_be_bytes(chunk.try_into().unwrap())) .collect::<Vec<f32>>(); - warn_debug!("Read {} bytes from serial port", n_doubles); + warn_debug!( + "Read {} ({} singles) bytes from serial port", + n_bytes, + n_singles + ); outputs.set(doubles.to_vec())?; Ok(()) diff --git a/src/serial.rs b/src/serial.rs index 731be06..95d08c2 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -59,7 +59,26 @@ impl SerialManager { let map = self.serial_map.read(); let port = map.get(name).ok_or(Error::SerialNotOpen)?; let mut buf = vec![0; n]; - port.lock().read_exact(&mut buf)?; + // implement a read exact to allow better error messages + let mut reader = port.lock(); + let mut filled = 0; + while filled < n { + match reader.read(&mut buf[filled..]) { + Ok(n) => filled += n, + Err(e) => match e.kind() { + std::io::ErrorKind::TimedOut => { + if filled == 0 { + return Err(Error::NoDataAvailable); + } + return Err(Error::IncompleteRead { + amount_read: filled, + inner: Box::new(Error::NoDataAvailable), + }); + } + _ => return Err(e.into()), + }, + } + } Ok(buf) } diff --git a/src/types.rs b/src/types.rs index c2e78b2..97fca4f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -16,7 +16,9 @@ pub trait IntoRustType<T> { impl IntoRustType<CString> for MxArray { fn into_rust(self) -> SResult<CString> { Ok(CharArray::from_mx_array(self) - .mexerr(Error::InvalidMatlabType("use a string instead".into()))? + .mexerr(Error::InvalidMatlabType( + "use a char array instead ('value')".into(), + ))? .get_cstring()) } } @@ -32,7 +34,7 @@ impl IntoRustType<f64> for MxArray { fn into_rust(self) -> SResult<f64> { let out = Numeric::<f64, _>::from_mx_array(self) .mexerr(Error::InvalidMatlabType( - "use a numerical type instead".into(), + "use a double numerical type instead".into(), ))? .data() .first() @@ -58,7 +60,7 @@ impl IntoRustType<Vec<f32>> for MxArray { fn into_rust(self) -> SResult<Vec<f32>> { let out = Numeric::<f32, _>::from_mx_array(self) .mexerr(Error::InvalidMatlabType( - "use a numerical type instead".into(), + "use an array of singles (floats) type instead".into(), ))? .data() .to_owned(); @@ -70,7 +72,7 @@ impl IntoRustType<Vec<f64>> for MxArray { fn into_rust(self) -> SResult<Vec<f64>> { let out = Numeric::<f64, _>::from_mx_array(self) .mexerr(Error::InvalidMatlabType( - "use a numerical type instead".into(), + "use an array of doubles type instead".into(), ))? .data() .to_owned(); -- GitLab