From 4e5c5f9c567c3a1a6e492a7a6c64001e27d81fb2 Mon Sep 17 00:00:00 2001 From: TomL94 <langer.tom7@gmail.com> Date: Wed, 8 Feb 2023 20:32:18 +0200 Subject: [PATCH 1/2] Implement FuzzyItem --- packages/storage/src/fuzzy_item.rs | 105 +++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 packages/storage/src/fuzzy_item.rs diff --git a/packages/storage/src/fuzzy_item.rs b/packages/storage/src/fuzzy_item.rs new file mode 100644 index 0000000..bcdcaa3 --- /dev/null +++ b/packages/storage/src/fuzzy_item.rs @@ -0,0 +1,105 @@ +use cosmwasm_std::{StdResult, Storage}; +use secret_toolkit_serialization::{Bincode2, Serde}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; + +use crate::Item; + +#[derive(Serialize, Deserialize)] +pub struct FuzzyData<T> { + data: T, + fuzz: u8, +} + +pub struct FuzzyItem<'a, T, Ser = Bincode2> +where + T: Serialize + DeserializeOwned + Copy, + Ser: Serde, +{ + item: Item<'a, FuzzyData<T>, Ser>, + storage: &'a mut dyn Storage, +} + +impl<'a, T: Serialize + DeserializeOwned + Copy, Ser: Serde> FuzzyItem<'a, T, Ser> { + pub fn new(item: Item<'a, FuzzyData<T>, Ser>, storage: &'a mut dyn Storage) -> Self { + Self { item, storage } + } + + pub fn add_suffix(&'a mut self, suffix: &[u8]) -> Self { + Self { + item: self.item.add_suffix(suffix), + storage: self.storage, + } + } +} + +impl<'a, T, Ser> Drop for FuzzyItem<'a, T, Ser> +where + T: Serialize + DeserializeOwned + Copy, + Ser: Serde, +{ + fn drop(&mut self) { + self.update(|fd| Ok(fd)).unwrap(); // This is not ideal but can't return `StdResult` + } +} + +impl<'a, T, Ser> FuzzyItem<'a, T, Ser> +where + T: Serialize + DeserializeOwned + Copy, + Ser: Serde, +{ + /// save will serialize the model and store, returns an error on serialization issues + pub fn save(&mut self, data: &T) -> StdResult<()> { + let new_data = match self.item.may_load(self.storage)? { + Some(fd) => FuzzyData { + data: *data, + fuzz: fd.fuzz.wrapping_add(1), + }, + None => FuzzyData { + data: *data, + fuzz: 0, + }, + }; + + self.item.save(self.storage, &new_data) + } + + /// userfacing remove function + pub fn remove(&mut self) { + self.item.remove(self.storage) + } + + /// load will return an error if no data is set at the given key, or on parse error + pub fn load(&self) -> StdResult<T> { + let fuzzy_data = self.item.load(self.storage)?; + Ok(fuzzy_data.data) + } + + /// may_load will parse the data stored at the key if present, returns `Ok(None)` if no data there. + /// returns an error on issues parsing + pub fn may_load(&self) -> StdResult<Option<T>> { + let maybe_fuzzy_data = self.item.may_load(self.storage)?; + Ok(maybe_fuzzy_data.map(|fd| fd.data)) + } + + /// efficient way to see if any object is currently saved. + pub fn is_empty(&self) -> bool { + self.item.is_empty(self.storage) + } + + /// Loads the data, perform the specified action, and store the result + /// in the database. This is shorthand for some common sequences, which may be useful. + /// + /// It assumes, that data was initialized before, and if it doesn't exist, `Err(StdError::NotFound)` + /// is returned. + pub fn update<A>(&mut self, action: A) -> StdResult<T> + where + A: FnOnce(T) -> StdResult<T>, + { + let mut fuzzy_data = self.item.load(self.storage)?; + let input = fuzzy_data.data; + fuzzy_data.data = action(input)?; + fuzzy_data.fuzz = fuzzy_data.fuzz.wrapping_add(1); + self.item.save(self.storage, &fuzzy_data)?; + Ok(fuzzy_data.data) + } +} From 79a069ce563fc77d828bc434bb66f3ddb83f61d7 Mon Sep 17 00:00:00 2001 From: TomL94 <langer.tom7@gmail.com> Date: Wed, 8 Feb 2023 20:32:28 +0200 Subject: [PATCH 2/2] Add to lib --- packages/storage/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/storage/src/lib.rs b/packages/storage/src/lib.rs index c6b0f14..1f17d28 100644 --- a/packages/storage/src/lib.rs +++ b/packages/storage/src/lib.rs @@ -2,6 +2,7 @@ pub mod append_store; pub mod deque_store; +pub mod fuzzy_item; pub mod item; pub mod keymap; pub mod keyset;