diff --git a/src/helpers.rs b/src/helpers.rs index c290c7e..0243f28 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -27,14 +27,6 @@ pub(crate) fn may_deserialize( } } -/// must_deserialize parses json bytes from storage (Option), returning NotFound error if no data present -pub(crate) fn must_deserialize(value: &Option>) -> StdResult { - match value { - Some(vec) => from_slice(vec), - None => Err(StdError::not_found(type_name::())), - } -} - /// 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 { @@ -120,10 +112,16 @@ pub(crate) fn query_raw( } } +/// Returns a debug identifier to explain what was not found +pub(crate) fn not_found_object_info(key: &[u8]) -> String { + let type_name = type_name::(); + 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)] @@ -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::(&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::(&[0xaa, 0xBB]), + "type: cw_storage_plus::helpers::test::Person; key: [AA, BB]" + ); + assert_eq!( + not_found_object_info::(&[]), + "type: cw_storage_plus::helpers::test::Person; key: []" + ); + assert_eq!( + not_found_object_info::(b"foo"), + "type: cosmwasm_std::math::uint128::Uint128; key: [66, 6F, 6F]" + ); } } diff --git a/src/item.rs b/src/item.rs index 70397fd..1f61526 100644 --- a/src/item.rs +++ b/src/item.rs @@ -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. @@ -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 { - 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::(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. diff --git a/src/path.rs b/src/path.rs index e6a3cb5..7b5b7eb 100644 --- a/src/path.rs +++ b/src/path.rs @@ -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)] @@ -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 { - 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::(&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.