use super::StorageMapper;
use crate::abi::{TypeAbi, TypeDescriptionContainer, TypeName};
use crate::api::{EndpointFinishApi, ErrorApi, StorageReadApi, StorageWriteApi};
use crate::io::EndpointResult;
use crate::storage::{storage_get, storage_set};
use crate::types::BoxedBytes;
use core::marker::PhantomData;
use dharitri_codec::{TopDecode, TopEncode};
pub struct SingleValueMapper<SA, T>
where
SA: StorageReadApi + StorageWriteApi + ErrorApi + Clone + 'static,
T: TopEncode + TopDecode + 'static,
{
api: SA,
key: BoxedBytes,
_phantom: core::marker::PhantomData<T>,
}
impl<SA, T> StorageMapper<SA> for SingleValueMapper<SA, T>
where
SA: StorageReadApi + StorageWriteApi + ErrorApi + Clone + 'static,
T: TopEncode + TopDecode,
{
fn new(api: SA, key: BoxedBytes) -> Self {
SingleValueMapper {
api,
key,
_phantom: PhantomData,
}
}
}
impl<SA, T> SingleValueMapper<SA, T>
where
SA: StorageReadApi + StorageWriteApi + ErrorApi + Clone + 'static,
T: TopEncode + TopDecode,
{
pub fn get(&self) -> T {
storage_get(self.api.clone(), self.key.as_slice())
}
pub fn set(&self, new_value: &T) {
storage_set(self.api.clone(), self.key.as_slice(), new_value);
}
pub fn is_empty(&self) -> bool {
self.api.storage_load_len(self.key.as_slice()) == 0
}
pub fn clear(&self) {
self.api.storage_store_slice_u8(self.key.as_slice(), &[]);
}
pub fn update<F: FnOnce(&mut T)>(&self, f: F) {
let mut value = self.get();
f(&mut value);
self.set(&value);
}
}
impl<SA, FA, T> EndpointResult<FA> for SingleValueMapper<SA, T>
where
SA: StorageReadApi + StorageWriteApi + ErrorApi + Clone + 'static,
FA: EndpointFinishApi + 'static,
T: TopEncode + TopDecode + EndpointResult<FA>,
{
fn finish(&self, api: FA) {
self.get().finish(api);
}
}
impl<SA, T> TypeAbi for SingleValueMapper<SA, T>
where
SA: StorageReadApi + StorageWriteApi + ErrorApi + Clone + 'static,
T: TopEncode + TopDecode + TypeAbi,
{
fn type_name() -> TypeName {
T::type_name()
}
fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
T::provide_type_descriptions(accumulator)
}
}