use alloc::vec::Vec;
use crate::allocation::{AllocationContext, AllocationError};
use crate::bytes::Payload;
use crate::bytes::{ReturnOutputByteCount, RuntimeStateByteCount};
use super::limits::StepCount;
#[derive(Debug, PartialEq, Eq)]
pub enum RunOutcome {
Stable(RuntimeStateSnapshot),
Return(ReturnOutput),
}
#[derive(Debug, PartialEq, Eq)]
pub struct RuntimeStateSnapshot {
bytes: Vec<u8>,
}
impl RuntimeStateSnapshot {
pub(crate) fn from_execution_state(bytes: Vec<u8>) -> Self {
Self { bytes }
}
pub(crate) fn from_runtime_state_view(bytes: Vec<u8>) -> Self {
Self { bytes }
}
pub(crate) fn from_trace_snapshot(bytes: Vec<u8>) -> Self {
Self { bytes }
}
#[must_use]
pub fn as_slice(&self) -> &[u8] {
&self.bytes
}
#[must_use]
pub fn into_raw_bytes(self) -> Vec<u8> {
self.bytes
}
#[must_use]
pub fn byte_count(&self) -> RuntimeStateByteCount {
RuntimeStateByteCount::new(self.bytes.len())
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct ReturnOutput {
bytes: Vec<u8>,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ReturnOutputView<'program> {
payload: &'program Payload,
}
impl ReturnOutput {
pub(crate) fn from_return_payload(bytes: Vec<u8>) -> Self {
Self { bytes }
}
pub(crate) fn from_trace_snapshot(bytes: Vec<u8>) -> Self {
Self { bytes }
}
#[must_use]
pub fn as_slice(&self) -> &[u8] {
&self.bytes
}
#[must_use]
pub fn into_raw_bytes(self) -> Vec<u8> {
self.bytes
}
#[must_use]
pub fn byte_count(&self) -> ReturnOutputByteCount {
ReturnOutputByteCount::new(self.bytes.len())
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
}
impl<'program> ReturnOutputView<'program> {
pub(crate) const fn new(payload: &'program Payload) -> Self {
Self { payload }
}
#[must_use]
pub fn byte_count(self) -> ReturnOutputByteCount {
ReturnOutputByteCount::from_payload_count(self.payload.byte_count())
}
#[must_use]
pub fn is_empty(self) -> bool {
self.byte_count().is_zero()
}
pub(crate) fn to_vec_with_context(
self,
context: AllocationContext,
) -> Result<Vec<u8>, AllocationError> {
self.payload.to_vec_with_context(context)
}
pub fn materialize(self) -> Result<ReturnOutput, AllocationError> {
Ok(ReturnOutput::from_return_payload(
self.to_vec_with_context(AllocationContext::ReturnOutput)?,
))
}
}
impl core::fmt::Debug for ReturnOutputView<'_> {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter
.debug_list()
.entries(self.payload.bytes())
.finish()
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct RunResult {
steps: StepCount,
outcome: RunOutcome,
}
impl RunResult {
pub(crate) fn stable(output: RuntimeStateSnapshot, steps: StepCount) -> Self {
Self {
steps,
outcome: RunOutcome::Stable(output),
}
}
pub(crate) fn from_return(output: ReturnOutput, steps: StepCount) -> Self {
Self {
steps,
outcome: RunOutcome::Return(output),
}
}
#[must_use]
pub const fn outcome(&self) -> &RunOutcome {
&self.outcome
}
#[must_use]
pub fn into_outcome(self) -> RunOutcome {
self.outcome
}
#[must_use]
pub const fn steps(&self) -> StepCount {
self.steps
}
}