Skip to content

Commit

Permalink
Better error messages for plugin communication
Browse files Browse the repository at this point in the history
  • Loading branch information
Robin Doer committed Jun 11, 2024
1 parent 93ff5a6 commit e572e5e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 21 deletions.
2 changes: 1 addition & 1 deletion nuts-directory/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl PluginHandler<DirectoryBackend<PathBuf>> for DirectoryPluginInformation {
) -> Result<HashMap<String, String>, ErrorResponse> {
match backend.info() {
Ok(info) => Ok([("block_size".to_string(), info.bsize.to_string())].into()),
Err(err) => Err(err.into()),
Err(err) => Err(ErrorResponse::backend::<DirectoryBackend<PathBuf>>(err)),
}
}
}
Expand Down
32 changes: 26 additions & 6 deletions nuts-tool-api/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

use nuts_backend::Backend;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
Expand Down Expand Up @@ -357,9 +358,6 @@ pub enum ErrorResponse {
/// Could not create an id from its binary representation.
InvalidIdData,

/// Could not convert the settings into its binary representation.
InvalidSettings,

/// Could not create the settings from its binary representation.
InvalidSettingsData,

Expand All @@ -369,12 +367,34 @@ pub enum ErrorResponse {
/// The header data has an invalid length.
InvalidHeaderBytes,

/// The attached backend raised an error.
Backend(String),

/// An arbitrary error with the given message occured.
Message(String),
}

impl<T: fmt::Display> From<T> for ErrorResponse {
fn from(msg: T) -> Self {
Self::Message(msg.to_string())
impl ErrorResponse {
pub fn message<T: AsRef<str>>(msg: T) -> ErrorResponse {
Self::Message(msg.as_ref().to_string())
}

pub fn backend<B: Backend>(err: B::Err) -> ErrorResponse {
Self::Backend(err.to_string())
}
}

impl fmt::Display for ErrorResponse {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::NotApplicable => write!(fmt, "the call is not applicable"),
Self::InvalidId => write!(fmt, "could not parse id"),
Self::InvalidIdData => write!(fmt, "could not create id"),
Self::InvalidSettingsData => write!(fmt, "could not create settings"),
Self::InvalidInfo => write!(fmt, "could not collect backend information"),
Self::InvalidHeaderBytes => write!(fmt, "invalid header bytes"),
Self::Backend(msg) => write!(fmt, "the backend created an error: {}", msg),
Self::Message(msg) => write!(fmt, "{}", msg),
}
}
}
31 changes: 18 additions & 13 deletions nuts-tool-api/src/plugin/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub trait PluginHandler<B: Backend> {

Ok(<B::Settings as Binary>::as_bytes(&settings))
}
None => Err(ErrorResponse::from("unable to make a create-builder")),
None => Err(ErrorResponse::message("unable to make a create-builder")),
}
}

Expand All @@ -111,8 +111,10 @@ pub trait PluginHandler<B: Backend> {
.ok_or(ErrorResponse::InvalidSettingsData)?;

match self.open_builder(args) {
Some(builder) => builder.build(settings).map_err(|err| err.into()),
None => Err(ErrorResponse::from("unable to make an open-builder")),
Some(builder) => builder
.build(settings)
.map_err(|err| ErrorResponse::backend::<B>(err)),
None => Err(ErrorResponse::message("unable to make an open-builder")),
}
}

Expand All @@ -126,8 +128,10 @@ pub trait PluginHandler<B: Backend> {
let header = into_header_bytes(header)?;

match self.create_builder(args) {
Some(builder) => builder.build(header, overwrite).map_err(|err| err.into()),
None => Err(ErrorResponse::from("unable to make a create-builder")),
Some(builder) => builder
.build(header, overwrite)
.map_err(|err| ErrorResponse::backend::<B>(err)),
None => Err(ErrorResponse::message("unable to make a create-builder")),
}
}

Expand All @@ -143,7 +147,7 @@ pub trait PluginHandler<B: Backend> {

/// Handles the [`Request::IdToBytes`] command.
fn handle_id_to_bytes(&self, str: &str) -> Result<Vec<u8>, ErrorResponse> {
let id = <B::Id as FromStr>::from_str(str).map_err(|_| ErrorResponse::InvalidIdData)?;
let id = <B::Id as FromStr>::from_str(str).map_err(|_| ErrorResponse::InvalidId)?;

Ok(<B::Id as Binary>::as_bytes(&id))
}
Expand All @@ -159,23 +163,23 @@ pub trait PluginHandler<B: Backend> {
fn handle_info(&self, backend: &B) -> Result<HashMap<String, String>, ErrorResponse> {
match backend.info() {
Ok(info) => Ok(self.info_to_hash(info).ok_or(ErrorResponse::InvalidInfo)?),
Err(err) => Err(err.into()),
Err(err) => Err(ErrorResponse::backend::<B>(err)),
}
}

/// Handles the [`Request::Aquire`] command.
fn handle_aquire(&self, backend: &mut B, bytes: &[u8]) -> Result<Vec<u8>, ErrorResponse> {
match B::aquire(backend, bytes) {
Ok(id) => Ok(<B::Id as Binary>::as_bytes(&id)),
Err(err) => Err(err.into()),
Err(err) => Err(ErrorResponse::backend::<B>(err)),
}
}

/// Handles the [`Request::Release`] command.
fn handle_release(&self, backend: &mut B, id: &[u8]) -> Result<(), ErrorResponse> {
let id = <B::Id as Binary>::from_bytes(id).ok_or(ErrorResponse::InvalidIdData)?;

B::release(backend, id).map_err(|err| err.into())
B::release(backend, id).map_err(|err| ErrorResponse::backend::<B>(err))
}

/// Handles the [`Request::ReadHeader`] command.
Expand All @@ -187,15 +191,15 @@ pub trait PluginHandler<B: Backend> {

match header.get_header_bytes(&mut bytes) {
Ok(()) => Ok(bytes.to_vec()),
Err(err) => Err(err.into()),
Err(err) => Err(ErrorResponse::backend::<B>(err)),
}
}

/// Handles the [`Request::WriteHeader`] command.
fn handle_write_header(&self, backend: &mut B, header: &[u8]) -> Result<(), ErrorResponse> {
let header = into_header_bytes(header)?;

B::write_header(backend, &header).map_err(|err| err.into())
B::write_header(backend, &header).map_err(|err| ErrorResponse::backend::<B>(err))
}

/// Handles the [`Request::Read`] command.
Expand All @@ -204,7 +208,8 @@ pub trait PluginHandler<B: Backend> {
let bsize = B::block_size(backend) as usize;
let mut buf = vec![0; bsize];

let nread = B::read(backend, &id, &mut buf)?;
let nread =
B::read(backend, &id, &mut buf).map_err(|err| ErrorResponse::backend::<B>(err))?;

Ok(buf[..nread].to_vec())
}
Expand All @@ -222,7 +227,7 @@ pub trait PluginHandler<B: Backend> {
let nbytes = cmp::min(bytes.len(), bsize);
let bytes = &bytes[..nbytes];

B::write(backend, &id, bytes).map_err(|err| err.into())
B::write(backend, &id, bytes).map_err(|err| ErrorResponse::backend::<B>(err))
}

fn handle_delete(&self, backend: B) -> Result<(), ErrorResponse> {
Expand Down
2 changes: 1 addition & 1 deletion nuts-tool-api/src/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub enum PluginError {
#[error(transparent)]
Bson(#[from] BsonError),

#[error("{0:?}")]
#[error("{0}")]
Response(ErrorResponse),

#[error("invalid response")]
Expand Down

0 comments on commit e572e5e

Please sign in to comment.