Skip to content

Commit

Permalink
Merge pull request #81 from CosmWasm/68-support-stderror
Browse files Browse the repository at this point in the history
Easy conversion to `cosmwasm_std::StdError`
  • Loading branch information
uint authored Nov 12, 2024
2 parents f53b3a7 + 75d2457 commit 9d67cf4
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 1 deletion.
2 changes: 2 additions & 0 deletions packages/cw-storey/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
mod backend;
pub mod containers;
mod encoding;
mod std_error;

pub use backend::CwStorage;
pub use encoding::CwEncoding;
pub use std_error::IntoStdError;
57 changes: 57 additions & 0 deletions packages/cw-storey/src/std_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/// A trait for converting *Storey* errors into [`cosmwasm_std::StdError`].
pub trait IntoStdError {
/// Converts the error into a [`cosmwasm_std::StdError`] for use with CosmWasm.
///
/// The error ends up as a [`cosmwasm_std::StdError::GenericErr`] with the error message
/// being the result of calling `to_string` on the error.
///
/// # Example
/// ```
/// use cosmwasm_std::StdError;
/// use storey::containers::map::key::ArrayDecodeError;
/// use cw_storey::IntoStdError as _;
///
/// let error = ArrayDecodeError::InvalidLength;
/// assert_eq!(error.into_std_error(), StdError::generic_err(error.to_string()));
/// ```
fn into_std_error(self) -> cosmwasm_std::StdError;
}

impl<T> IntoStdError for T
where
T: storey::error::StoreyError,
{
fn into_std_error(self) -> cosmwasm_std::StdError {
cosmwasm_std::StdError::generic_err(self.to_string())
}
}

#[cfg(test)]
mod tests {
use cosmwasm_std::StdError;
use storey::error::StoreyError;

use super::*;

#[derive(Debug)]
struct MockError {
msg: String,
}

impl std::fmt::Display for MockError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.msg)
}
}

impl StoreyError for MockError {}

#[test]
fn test_into_std_error() {
let error = MockError {
msg: "An error occurred".to_string(),
};
let std_error: StdError = error.into_std_error();
assert_eq!(std_error, StdError::generic_err("An error occurred"));
}
}
2 changes: 2 additions & 0 deletions packages/storey/src/containers/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ pub enum TryGetError<E> {
#[error(transparent)]
DecodeError(#[from] E),
}

impl<T: std::fmt::Display> crate::error::StoreyError for TryGetError<T> {}
8 changes: 8 additions & 0 deletions packages/storey/src/containers/map/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ impl Key for str {
#[error("invalid UTF8")]
pub struct InvalidUtf8;

impl crate::error::StoreyError for InvalidUtf8 {}

impl OwnedKey for String {
type Error = InvalidUtf8;

Expand Down Expand Up @@ -128,10 +130,14 @@ impl OwnedKey for Box<[u8]> {
}

/// An error type for decoding arrays.
#[derive(Debug, PartialEq, Eq, Clone, Copy, thiserror::Error)]
pub enum ArrayDecodeError {
#[error("invalid length")]
InvalidLength,
}

impl crate::error::StoreyError for ArrayDecodeError {}

impl<const N: usize> OwnedKey for [u8; N] {
type Error = ArrayDecodeError;

Expand Down Expand Up @@ -181,6 +187,8 @@ pub enum NumericKeyDecodeError {
InvalidLength,
}

impl crate::error::StoreyError for NumericKeyDecodeError {}

macro_rules! impl_key_for_numeric {
($($t:ty),*) => {
$(
Expand Down
2 changes: 2 additions & 0 deletions packages/storey/src/containers/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ pub enum MapKeyDecodeError<I: std::fmt::Display> {
Inner(I),
}

impl<I: std::fmt::Display> crate::error::StoreyError for MapKeyDecodeError<I> {}

/// An accessor for a map.
///
/// The accessor provides methods for interacting with the map in storage.
Expand Down
6 changes: 5 additions & 1 deletion packages/storey/src/containers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,16 @@ pub trait Storable {
}

/// A key-value pair decoding error.
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, thiserror::Error)]
pub enum KVDecodeError<K, V> {
#[error("failed to decode key: {0}")]
Key(K),
#[error("failed to decode value: {0}")]
Value(V),
}

impl<K: std::fmt::Display, V: std::fmt::Display> crate::error::StoreyError for KVDecodeError<K, V> {}

/// A trait for collection accessors (see [`Storable::Accessor`]) that provide iteration over
/// their contents.
pub trait IterableAccessor: Sized {
Expand Down
7 changes: 7 additions & 0 deletions packages/storey/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use std::fmt::Display;

/// A trait representing a Storey error.
///
/// This trait is implemented for all Storey error types, allowing third-party crates
/// to implement extension traits for all of those error types.
pub trait StoreyError: Display {}
1 change: 1 addition & 0 deletions packages/storey/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@

pub mod containers;
pub mod encoding;
pub mod error;
pub mod storage;

0 comments on commit 9d67cf4

Please sign in to comment.