use cosmwasm_std::Order;
use cosmwasm_std::Storage;
use std::collections::BTreeMap;
use std::iter;
use std::ops::{Bound, RangeBounds};
#[derive(Default)]
/// In-memory [`Storage`] implementation used for tests and host-side execution.
pub struct MemoryStorage {
data: BTreeMap<Vec<u8>, Vec<u8>>,
}
impl MemoryStorage {
/// Creates an empty in-memory storage backend.
pub fn new() -> Self {
Self::default()
}
}
impl Storage for MemoryStorage {
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
self.data.get(key).cloned()
}
fn set(&mut self, key: &[u8], value: &[u8]) {
if value.is_empty() {
panic!(
"TL;DR: Value must not be empty in Storage::set but in most cases you can use Storage::remove instead. Long story: Getting empty values from storage is not well supported at the moment. Some of our internal interfaces cannot differentiate between a non-existent key and an empty value. Right now, you cannot rely on the behaviour of empty values. To protect you from trouble later on, we stop here. Sorry for the inconvenience! We highly welcome you to contribute to CosmWasm, making this more solid one way or the other."
);
}
self.data.insert(key.to_vec(), value.to_vec());
}
fn remove(&mut self, key: &[u8]) {
self.data.remove(key);
}
fn range<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
order: Order,
) -> Box<dyn Iterator<Item = (Vec<u8>, Vec<u8>)> + 'a> {
let bounds = range_bounds(start, end);
match (bounds.start_bound(), bounds.end_bound()) {
(Bound::Included(start), Bound::Excluded(end)) if start > end => {
return Box::new(iter::empty());
}
_ => {}
}
let iter = self.data.range(bounds);
match order {
Order::Ascending => Box::new(iter.map(clone_item)),
Order::Descending => Box::new(iter.rev().map(clone_item)),
}
}
}
fn range_bounds(start: Option<&[u8]>, end: Option<&[u8]>) -> impl RangeBounds<Vec<u8>> {
(
start.map_or(Bound::Unbounded, |x| Bound::Included(x.to_vec())),
end.map_or(Bound::Unbounded, |x| Bound::Excluded(x.to_vec())),
)
}
type BTreeMapRecordRef<'a> = (&'a Vec<u8>, &'a Vec<u8>);
fn clone_item(item_ref: BTreeMapRecordRef) -> (Vec<u8>, Vec<u8>) {
let (key, value) = item_ref;
(key.clone(), value.clone())
}