corevm-guest 0.1.28

API/SDK for CoreVM guest programs
Documentation
//! Host messages.

#![allow(clippy::missing_safety_doc)]

use crate::c;
use corevm_types::{flags::RecvMessage, RecvHostMessageOutcome};

/// Pop the next host message from the incoming messages queue.
///
/// Returns `None` if the queue is empty.
///
/// This is a non-blocking variant of [`recv_host_message`].
#[cfg(feature = "alloc")]
pub fn try_recv_host_message() -> Option<alloc::vec::Vec<u8>> {
	let outcome = unsafe { c::recv_host_message(0, 0, RecvMessage::NON_BLOCKING.bits()) };
	let len = RecvHostMessageOutcome::from_reg(outcome).into_inner()?;
	let mut buf = alloc::vec::Vec::with_capacity(len as usize);
	unsafe {
		c::recv_host_message(
			buf.as_mut_ptr() as u64,
			u64::from(len),
			RecvMessage::NON_BLOCKING.bits(),
		)
	};
	unsafe { buf.set_len(len as usize) };
	Some(buf)
}

/// Pop the next host message from the incoming messages queue into the supplied buffer.
///
/// Returns `None` if the queue is empty.
/// Returns `Some(Err(n))` where `n` is the message size if the buffer is too small.
/// On success returns `Some(Ok(n))` where `n` is the message size.
///
/// This is a non-blocking variant of [`recv_host_message_into`].
#[inline]
pub fn try_recv_host_message_into(buf: &mut [u8]) -> Option<Result<usize, usize>> {
	let outcome = unsafe {
		c::recv_host_message(
			buf.as_mut_ptr() as u64,
			buf.len() as u64,
			RecvMessage::NON_BLOCKING.bits(),
		)
	};
	let len = RecvHostMessageOutcome::from_reg(outcome).into_inner()?;
	if u64::from(len) > buf.len() as u64 {
		return Some(Err(len as usize));
	}
	Some(Ok(len as usize))
}

/// Pop the next host message from the incoming messages queue into the supplied buffer.
///
/// If the buffer is too small, the message is silently discarded.
///
/// Returns `None` if the queue is empty.
/// On success returns `Some(n)` where `n` is the message size.
///
/// This is a non-blocking variant of [`recv_bounded_host_message_into`].
#[inline]
pub fn try_recv_bounded_host_message_into(buf: &mut [u8]) -> Option<usize> {
	let outcome = unsafe {
		c::recv_host_message(
			buf.as_mut_ptr() as u64,
			buf.len() as u64,
			RecvMessage::DISCARD.bits() | RecvMessage::NON_BLOCKING.bits(),
		)
	};
	let len = RecvHostMessageOutcome::from_reg(outcome).into_inner()?;
	Some(len as usize)
}

/// Pop the next host message from the incoming messages queue.
///
/// Blocks execution if the queue is empty until new data arrives.
/// For a non-blocking variant see [`try_recv_host_message`].
#[cfg(feature = "alloc")]
pub fn recv_host_message() -> alloc::vec::Vec<u8> {
	let outcome = unsafe { c::recv_host_message(0, 0, 0) };
	let len = RecvHostMessageOutcome::from_reg(outcome)
		.into_inner()
		.expect("The call is blocking");
	let mut buf = alloc::vec::Vec::with_capacity(len as usize);
	unsafe { c::recv_host_message(buf.as_mut_ptr() as u64, u64::from(len), 0) };
	unsafe { buf.set_len(len as usize) };
	buf
}

/// Pop the next host message from the incoming messages queue into the supplied buffer.
///
/// Blocks execution if the queue is empty until new data arrives.
/// For a non-blocking variant see [`try_recv_host_message_into`].
///
/// Returns `Err(n)` where `n` is the message size if the buffer is too small.
/// On success returns `Ok(n)` where `n` is the message size.
#[inline]
pub fn recv_host_message_into(buf: &mut [u8]) -> Result<usize, usize> {
	let outcome = unsafe { c::recv_host_message(buf.as_mut_ptr() as u64, buf.len() as u64, 0) };
	let len = RecvHostMessageOutcome::from_reg(outcome)
		.into_inner()
		.expect("The call is blocking");
	if u64::from(len) > buf.len() as u64 {
		return Err(len as usize);
	}
	Ok(len as usize)
}

/// Pop the next host message from the incoming messages queue into the supplied buffer.
///
/// If the buffer is too small, the message is silently discarded.
///
/// Blocks execution if the queue is empty until new data arrives.
/// For a non-blocking variant see [`try_recv_bounded_host_message_into`].
///
/// Returns the message size.
#[inline]
pub fn recv_bounded_host_message_into(buf: &mut [u8]) -> Option<usize> {
	let outcome = unsafe {
		c::recv_host_message(buf.as_mut_ptr() as u64, buf.len() as u64, RecvMessage::DISCARD.bits())
	};
	let len = RecvHostMessageOutcome::from_reg(outcome)
		.into_inner()
		.expect("The call is blocking");
	Some(len as usize)
}