use crate::StorageError;
use core::marker::PhantomData;
use tezos_smart_rollup_host::path::{concat, OwnedPath, Path};
use tezos_smart_rollup_host::runtime::{Runtime, RuntimeError, ValueType};
pub(crate) struct Layer<T: From<OwnedPath>> {
pub(crate) path: OwnedPath,
phantom: PhantomData<T>,
}
fn has_subtree_res(v: Result<Option<ValueType>, RuntimeError>) -> bool {
use ValueType::*;
matches!(v, Ok(Some(Subtree | ValueWithSubtree)))
}
impl<T: From<OwnedPath>> Layer<T> {
pub(crate) fn with_path(name: &impl Path) -> Self {
Self {
path: OwnedPath::from(name),
phantom: PhantomData,
}
}
pub(crate) fn force_make_copy(
&self,
host: &mut impl Runtime,
name: &impl Path,
) -> Result<Self, StorageError> {
let copy = Self {
path: OwnedPath::from(name),
phantom: PhantomData,
};
match host.store_copy(&self.path, ©.path) {
Ok(()) | Err(RuntimeError::PathNotFound) => Ok(copy),
Err(e) => Err(e.into()),
}
}
pub(crate) fn consume(
&mut self,
host: &mut impl Runtime,
layer: Layer<T>,
) -> Result<(), StorageError> {
if let Ok(Some(_)) = host.store_has(&layer.path) {
host.store_move(&layer.path, &self.path)
.map_err(StorageError::from)
} else if let Ok(Some(_)) = host.store_has(&self.path) {
host.store_delete(&self.path).map_err(StorageError::from)
} else {
Ok(())
}
}
pub(crate) fn create_new(
&mut self,
host: &impl Runtime,
id: &impl Path,
) -> Result<Option<T>, StorageError> {
let account_path = concat(&self.path, id)?;
if has_subtree_res(host.store_has(&account_path)) {
Ok(None)
} else {
Ok(Some(T::from(account_path)))
}
}
pub(crate) fn get(
&self,
host: &impl Runtime,
id: &impl Path,
) -> Result<Option<T>, StorageError> {
let account_path = concat(&self.path, id)?;
if has_subtree_res(host.store_has(&account_path)) {
Ok(Some(T::from(account_path)))
} else {
Ok(None)
}
}
pub(crate) fn get_or_create(
&self,
_host: &impl Runtime,
id: &impl Path,
) -> Result<T, StorageError> {
let account_path = concat(&self.path, id)?;
Ok(T::from(account_path))
}
pub(crate) fn delete(
&mut self,
host: &mut impl Runtime,
id: &impl Path,
) -> Result<(), StorageError> {
let account_path = concat(&self.path, id)?;
host.store_delete(&account_path).map_err(StorageError::from)
}
pub(crate) fn discard(self, host: &mut impl Runtime) -> Result<(), StorageError> {
if let Ok(Some(_)) = host.store_has(&self.path) {
host.store_delete(&self.path).map_err(StorageError::from)
} else {
Ok(())
}
}
}