use fvm_shared::error::ExitCode;
use fvm_shared::sys::out::vm::MessageContext;
use super::Context;
use super::error::Abort;
use crate::kernel::MessageOps;
const MAX_MESSAGE_LEN: usize = 1024;
pub fn exit(
context: Context<'_, impl Sized>, code: u32,
blk: u32,
message_off: u32,
message_len: u32,
) -> Abort {
let code = ExitCode::new(code);
if !code.is_success() && code.is_system_error() {
return Abort::Exit(
ExitCode::SYS_ILLEGAL_EXIT_CODE,
format!("actor aborted with code {}", code),
blk,
);
}
let message = if message_len == 0 {
"actor aborted".to_owned()
} else {
match context.memory.try_slice(message_off, message_len) {
Ok(bytes) => {
if bytes.len() > MAX_MESSAGE_LEN {
let prefix = &bytes[..(MAX_MESSAGE_LEN / 2)];
let suffix = &bytes[bytes.len() - (MAX_MESSAGE_LEN / 2)..];
format!(
"{} ... (skipped {} bytes) ... {}",
String::from_utf8_lossy(prefix),
bytes.len() - MAX_MESSAGE_LEN,
String::from_utf8_lossy(suffix)
)
} else {
String::from_utf8_lossy(bytes).into_owned()
}
}
Err(e) => format!("failed to extract error message: {e}"),
}
};
Abort::Exit(code, message, blk)
}
pub fn message_context(
context: Context<'_, impl MessageOps>,
) -> crate::kernel::Result<MessageContext> {
context.kernel.msg_context()
}