use super::{HashWork, Memory, MemoryError, OwnedMap, OwnedVec, allocator};
use crate::limits::BudgetView;
mod private {
pub trait Sealed {}
}
pub trait Work: Clone + private::Sealed {
type Retained: core::fmt::Debug;
fn retain_storage(&self) -> Self::Retained;
fn into_storage_owner(self, retained: Self::Retained) -> Memory;
fn with_storage_owner(&self, memory: Memory) -> (Self, Self::Retained);
fn memory(&self) -> &Memory;
fn charge_work(&self, amount: u64) -> Result<(), MemoryError>;
#[must_use]
fn vector<T>(&self) -> OwnedVec<T, Self> {
OwnedVec {
values: allocator_api2::vec::Vec::new_in(allocator::AccountAllocator::new(
self.clone(),
)),
}
}
#[must_use]
fn map<K: HashWork, V>(&self) -> OwnedMap<K, V, Self> {
OwnedMap::new(self.clone())
}
}
impl private::Sealed for Memory {}
impl Work for Memory {
type Retained = ();
fn retain_storage(&self) {}
fn into_storage_owner(self, (): ()) -> Memory {
self
}
fn with_storage_owner(&self, memory: Memory) -> (Self, ()) {
(memory, ())
}
fn memory(&self) -> &Memory {
self
}
fn charge_work(&self, amount: u64) -> Result<(), MemoryError> {
Memory::charge_work(self, amount)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Execution<'a> {
memory: &'a Memory,
budget: BudgetView<'a>,
}
impl<'a> Execution<'a> {
pub(crate) fn new(memory: &'a Memory, budget: BudgetView<'a>) -> Self {
Self { memory, budget }
}
}
impl private::Sealed for Execution<'_> {}
impl Work for Execution<'_> {
type Retained = Memory;
fn retain_storage(&self) -> Memory {
self.memory.clone()
}
fn into_storage_owner(self, retained: Memory) -> Memory {
retained
}
fn with_storage_owner(&self, memory: Memory) -> (Self, Memory) {
(*self, memory)
}
fn memory(&self) -> &Memory {
self.memory
}
fn charge_work(&self, amount: u64) -> Result<(), MemoryError> {
self.budget
.work_in(amount, self.memory)
.map_err(|_| MemoryError::WorkExceeded)
}
}