use crate::{
engine::executor::{Cell, CellError, LiftFromCells, LiftFromCellsByValue, LowerToCells},
store::AsStoreId,
};
use core::{cmp::max, ptr::NonNull, slice};
#[derive(Debug)]
pub struct InOutParams {
cells: NonNull<Cell>,
len_params: usize,
len_results: usize,
}
impl InOutParams {
pub fn empty() -> Self {
Self {
cells: <NonNull<[Cell]>>::from(&mut [][..]).cast::<Cell>(),
len_params: 0,
len_results: 0,
}
}
pub unsafe fn new(
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: NonNull::from(cells).cast::<Cell>(),
len_params,
len_results,
})
}
#[inline]
unsafe fn params(&self) -> &[Cell] {
unsafe { slice::from_raw_parts(self.cells.as_ptr(), self.len_params) }
}
#[inline]
unsafe fn results_mut(&mut self) -> &mut [Cell] {
unsafe { slice::from_raw_parts_mut(self.cells.as_ptr(), self.len_results) }
}
pub fn decode_params_into<T>(&self, store: impl AsStoreId, out: T) -> Result<(), CellError>
where
T: LiftFromCells<Value = ()>,
{
let mut param_cells = unsafe { self.params() };
out.lift_from_cells(store, &mut param_cells)
}
pub fn decode_params<T>(&self, store: impl AsStoreId) -> Result<T, CellError>
where
T: LiftFromCellsByValue,
{
let mut param_cells = unsafe { self.params() };
<T as LiftFromCellsByValue>::lift_from_cells_by_value(store, &mut param_cells)
}
pub fn encode_results<T>(
mut self,
store: impl AsStoreId,
results: T,
) -> Result<InOutResults, CellError>
where
T: LowerToCells,
{
let mut result_cells = unsafe { self.results_mut() };
results.lower_to_cells(store, &mut result_cells)?;
Ok(InOutResults {
_seal: private::Seal,
})
}
}
#[derive(Debug)]
pub struct InOutResults {
_seal: private::Seal,
}
mod private {
#[derive(Debug)]
pub struct Seal;
}