use crate::{
engine::executor::{Cell, CellError, LiftFromCells, LiftFromCellsByValue, LowerToCells},
store::AsStoreId,
};
use core::cmp::max;
/// Wrapper around a slice of [`Cell`]s to manage reading parameters and writing results of a function call.
#[derive(Debug)]
pub struct InOutParams<'cells> {
/// The underlying slice of cells used for both parameters and results.
cells: &'cells mut [Cell],
/// The number of cells used for parameters.
///
/// # Note
///
/// Must be less than or equal to the length of `cells`.
len_params: usize,
/// The number of cells used for results.
///
/// # Note
///
/// Must be less than or equal to the length of `cells`.
len_results: usize,
}
impl<'cells> InOutParams<'cells> {
/// Creates a new [`InOutParams`] from the given parts.
///
/// # Errors
///
/// If max(len_params, len_results) is not equal to `cells.len()`.
pub fn new(
cells: &'cells mut [Cell],
len_params: usize,
len_results: usize,
) -> Result<Self, CellError> {
let required_cells = max(len_params, len_results);
if required_cells < cells.len() {
return Err(CellError::NotEnoughValues);
}
if required_cells > cells.len() {
return Err(CellError::NotEnoughCells);
}
Ok(Self {
cells,
len_params,
len_results,
})
}
/// Returns the slice of [`Cell`] parameters.
pub fn params(&self) -> &[Cell] {
&self.cells[..self.len_params]
}
/// Decodes the parameter slice of [`Cell`]s into `T` if possible.
///
/// Returns a [`CellError`], otherwise.
pub fn decode_params_into<T>(&self, store: impl AsStoreId, out: T) -> Result<(), CellError>
where
T: LiftFromCells<Value = ()>,
{
out.lift_from_cells(store, &mut self.params())
}
/// Decodes the parameter slice of [`Cell`]s into `T` if possible.
///
/// Returns a [`CellError`], otherwise.
pub fn decode_params<T>(&self, store: impl AsStoreId) -> Result<T, CellError>
where
T: LiftFromCellsByValue,
{
<T as LiftFromCellsByValue>::lift_from_cells_by_value(store, &mut self.params())
}
/// Encodes the `results` of type `T` into the result [`Cell`]s if possible.
///
/// Returns a [`CellError`], otherwise.
pub fn encode_results<T>(
self,
store: impl AsStoreId,
results: T,
) -> Result<InOutResults<'cells>, CellError>
where
T: LowerToCells,
{
let mut cells = &mut self.cells[..self.len_results];
results.lower_to_cells(store, &mut cells)?;
Ok(InOutResults { cells })
}
}
/// The result [`Cell`]s of a (host) function invocation.
#[derive(Debug)]
pub struct InOutResults<'cells> {
/// The underlying [`Cell`]s representing the encoded results.
cells: &'cells mut [Cell],
}
impl<'cells> InOutResults<'cells> {
/// Returns the slice of [`Cell`] results.
pub fn results(&self) -> &[Cell] {
self.cells
}
}
use crate::;
use max;
/// Wrapper around a slice of [`Cell`]s to manage reading parameters and writing results of a function call.
/// The result [`Cell`]s of a (host) function invocation.