Skip to content

Commit

Permalink
Inline must_deserialize and improve error message
Browse files Browse the repository at this point in the history
  • Loading branch information
webmaster128 authored and chipshort committed Nov 13, 2023
1 parent bd30762 commit 8a1bb1c
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 38 deletions.
50 changes: 20 additions & 30 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ pub(crate) fn may_deserialize<T: DeserializeOwned>(
}
}

/// must_deserialize parses json bytes from storage (Option), returning NotFound error if no data present
pub(crate) fn must_deserialize<T: DeserializeOwned>(value: &Option<Vec<u8>>) -> StdResult<T> {
match value {
Some(vec) => from_slice(vec),
None => Err(StdError::not_found(type_name::<T>())),
}
}

/// This is equivalent concat(to_length_prefixed_nested(namespaces), key)
/// But more efficient when the intermediate namespaces often must be recalculated
pub(crate) fn namespaces_with_key(namespaces: &[&[u8]], key: &[u8]) -> Vec<u8> {
Expand Down Expand Up @@ -120,10 +112,16 @@ pub(crate) fn query_raw<Q: CustomQuery>(
}
}

/// Returns a debug identifier to explain what was not found
pub(crate) fn not_found_object_info<T>(key: &[u8]) -> String {
let type_name = type_name::<T>();
format!("type: {type_name}; key: {:02X?}", key)
}

#[cfg(test)]
mod test {
use super::*;
use cosmwasm_std::{to_vec, StdError};
use cosmwasm_std::{to_vec, Uint128};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, PartialEq, Debug)]
Expand Down Expand Up @@ -169,26 +167,18 @@ mod test {
}

#[test]
fn must_deserialize_handles_some() {
let person = Person {
name: "Maria".to_string(),
age: 42,
};
let value = to_vec(&person).unwrap();
let loaded = Some(value);

let parsed: Person = must_deserialize(&loaded).unwrap();
assert_eq!(parsed, person);
}

#[test]
fn must_deserialize_handles_none() {
let parsed = must_deserialize::<Person>(&None);
match parsed.unwrap_err() {
StdError::NotFound { kind, .. } => {
assert_eq!(kind, "cw_storage_plus::helpers::test::Person")
}
e => panic!("Unexpected error {}", e),
}
fn not_found_object_info_works() {
assert_eq!(
not_found_object_info::<Person>(&[0xaa, 0xBB]),
"type: cw_storage_plus::helpers::test::Person; key: [AA, BB]"
);
assert_eq!(
not_found_object_info::<Person>(&[]),
"type: cw_storage_plus::helpers::test::Person; key: []"
);
assert_eq!(
not_found_object_info::<Uint128>(b"foo"),
"type: cosmwasm_std::math::uint128::Uint128; key: [66, 6F, 6F]"
);
}
}
12 changes: 8 additions & 4 deletions src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use serde::Serialize;
use std::marker::PhantomData;

use cosmwasm_std::{
to_vec, Addr, CustomQuery, QuerierWrapper, StdError, StdResult, Storage, WasmQuery,
from_slice, to_vec, Addr, CustomQuery, QuerierWrapper, StdError, StdResult, Storage, WasmQuery,
};

use crate::helpers::{may_deserialize, must_deserialize};
use crate::helpers::{may_deserialize, not_found_object_info};

/// Item stores one typed item at the given key.
/// This is an analog of Singleton.
Expand Down Expand Up @@ -48,8 +48,12 @@ where

/// load will return an error if no data is set at the given key, or on parse error
pub fn load(&self, store: &dyn Storage) -> StdResult<T> {
let value = store.get(self.storage_key);
must_deserialize(&value)
if let Some(value) = store.get(self.storage_key) {
from_slice(&value)
} else {
let object_info = not_found_object_info::<T>(self.storage_key);
Err(StdError::not_found(object_info))
}
}

/// may_load will parse the data stored at the key if present, returns `Ok(None)` if no data there.
Expand Down
12 changes: 8 additions & 4 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use serde::de::DeserializeOwned;
use serde::Serialize;
use std::marker::PhantomData;

use crate::helpers::{may_deserialize, must_deserialize, nested_namespaces_with_key};
use crate::helpers::{may_deserialize, nested_namespaces_with_key, not_found_object_info};
use crate::keys::Key;
use cosmwasm_std::{to_vec, StdError, StdResult, Storage};
use cosmwasm_std::{from_slice, to_vec, StdError, StdResult, Storage};
use std::ops::Deref;

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -62,8 +62,12 @@ where

/// load will return an error if no data is set at the given key, or on parse error
pub fn load(&self, store: &dyn Storage) -> StdResult<T> {
let value = store.get(&self.storage_key);
must_deserialize(&value)
if let Some(value) = store.get(&self.storage_key) {
from_slice(&value)
} else {
let object_info = not_found_object_info::<T>(&self.storage_key);
Err(StdError::not_found(object_info))
}
}

/// may_load will parse the data stored at the key if present, returns Ok(None) if no data there.
Expand Down

0 comments on commit 8a1bb1c

Please sign in to comment.