#[cfg(feature = "marine")]
use marine_rs_sdk::marine;
#[cfg(feature = "marine")]
use fluence_it_types::IValue;
use serde::Deserialize;
use serde::Serialize;
pub const INTERPRETER_SUCCESS: i64 = 0;
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SoftLimitsTriggering {
pub air_size_limit_exceeded: bool,
pub particle_size_limit_exceeded: bool,
pub call_result_size_limit_exceeded: bool,
}
#[cfg_attr(feature = "marine", marine)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct InterpreterOutcome {
pub ret_code: i64,
pub error_message: String,
pub data: Vec<u8>,
pub next_peer_pks: Vec<String>,
pub call_requests: Vec<u8>,
pub air_size_limit_exceeded: bool,
pub particle_size_limit_exceeded: bool,
pub call_result_size_limit_exceeded: bool,
}
impl SoftLimitsTriggering {
pub fn new(
air_size_limit_exceeded: bool,
particle_size_limit_exceeded: bool,
call_result_size_limit_exceeded: bool,
) -> Self {
Self {
air_size_limit_exceeded,
particle_size_limit_exceeded,
call_result_size_limit_exceeded,
}
}
pub fn are_limits_exceeded(&self) -> bool {
self.air_size_limit_exceeded
|| self.particle_size_limit_exceeded
|| self.call_result_size_limit_exceeded
}
}
impl InterpreterOutcome {
pub fn new(
ret_code: i64,
error_message: String,
data: Vec<u8>,
next_peer_pks: Vec<String>,
call_requests: SerializedCallRequests,
soft_limits_triggering: SoftLimitsTriggering,
) -> Self {
let call_requests = call_requests.into();
Self {
ret_code,
error_message,
data,
next_peer_pks,
call_requests,
air_size_limit_exceeded: soft_limits_triggering.air_size_limit_exceeded,
particle_size_limit_exceeded: soft_limits_triggering.particle_size_limit_exceeded,
call_result_size_limit_exceeded: soft_limits_triggering.call_result_size_limit_exceeded,
}
}
}
#[cfg(feature = "marine")]
impl InterpreterOutcome {
pub fn from_ivalue(ivalue: IValue) -> Result<Self, String> {
const OUTCOME_FIELDS_COUNT: usize = 8;
let mut record_values = try_as_record(ivalue)?.into_vec();
if record_values.len() != OUTCOME_FIELDS_COUNT {
return Err(format!(
"expected InterpreterOutcome struct with {OUTCOME_FIELDS_COUNT} fields, got {record_values:?}"
));
}
let call_result_size_limit_exceeded = try_as_boolean(
record_values.pop().unwrap(),
"call_result_size_limit_exceeded",
)?;
let particle_size_limit_exceeded =
try_as_boolean(record_values.pop().unwrap(), "particle_size_limit_exceeded")?;
let air_size_limit_exceeded =
try_as_boolean(record_values.pop().unwrap(), "air_size_limit_exceeded")?;
let call_requests = try_as_byte_vec(record_values.pop().unwrap(), "call_requests")?;
let next_peer_pks = try_as_string_vec(record_values.pop().unwrap(), "next_peer_pks")?;
let data = try_as_byte_vec(record_values.pop().unwrap(), "data")?;
let error_message = try_as_string(record_values.pop().unwrap(), "error_message")?;
let ret_code = try_as_i64(record_values.pop().unwrap(), "ret_code")?;
let soft_limits_triggering = SoftLimitsTriggering::new(
air_size_limit_exceeded,
particle_size_limit_exceeded,
call_result_size_limit_exceeded,
);
let outcome = Self::new(
ret_code,
error_message,
data,
next_peer_pks,
call_requests.into(),
soft_limits_triggering,
);
Ok(outcome)
}
}
#[cfg(feature = "marine")]
use fluence_it_types::ne_vec::NEVec;
use crate::SerializedCallRequests;
#[cfg(feature = "marine")]
fn try_as_record(ivalue: IValue) -> Result<NEVec<IValue>, String> {
match ivalue {
IValue::Record(record_values) => Ok(record_values),
v => Err(format!("expected record for InterpreterOutcome, got {v:?}")),
}
}
#[cfg(feature = "marine")]
fn try_as_i64(ivalue: IValue, field_name: &str) -> Result<i64, String> {
match ivalue {
IValue::S64(value) => Ok(value),
v => Err(format!("expected an i64 for {field_name}, got {v:?}")),
}
}
#[cfg(feature = "marine")]
pub fn try_as_string(ivalue: IValue, field_name: &str) -> Result<String, String> {
match ivalue {
IValue::String(value) => Ok(value),
v => Err(format!("expected a string for {field_name}, got {v:?}")),
}
}
#[cfg(feature = "marine")]
fn try_as_byte_vec(ivalue: IValue, field_name: &str) -> Result<Vec<u8>, String> {
let byte_vec = match ivalue {
IValue::Array(array) => {
let array: Result<Vec<_>, _> = array
.into_iter()
.map(|v| match v {
IValue::U8(byte) => Ok(byte),
v => Err(format!("expected a byte, got {v:?}")),
})
.collect();
array?
}
IValue::ByteArray(array) => array,
v => return Err(format!("expected a Vec<u8> for {field_name}, got {v:?}")),
};
Ok(byte_vec)
}
#[cfg(feature = "marine")]
fn try_as_string_vec(ivalue: IValue, field_name: &str) -> Result<Vec<String>, String> {
match ivalue {
IValue::Array(ar_values) => {
let array = ar_values
.into_iter()
.map(|v| match v {
IValue::String(str) => Ok(str),
v => Err(format!("expected string for next_peer_pks, got {v:?}")),
})
.collect::<Result<Vec<String>, _>>()?;
Ok(array)
}
v => Err(format!("expected an array for {field_name}, got {v:?}")),
}
}
#[cfg(feature = "marine")]
fn try_as_boolean(ivalue: IValue, field_name: &str) -> Result<bool, String> {
match ivalue {
IValue::Boolean(value) => Ok(value),
v => Err(format!("expected a bool for {field_name}, got {v:?}")),
}
}