use core::mem;
use core::slice;
#[sel4_cfg(KERNEL_INVOCATION_REPORT_ERROR_IPC)]
use core::str::{self, Utf8Error};
use crate::{cap, newtype_methods, sel4_cfg, sys, AbsoluteCPtr, Word};
#[sel4_cfg(KERNEL_INVOCATION_REPORT_ERROR_IPC)]
use crate::const_helpers::u32_into_usize;
#[derive(Default)]
#[repr(transparent)]
pub struct IpcBuffer(sys::seL4_IPCBuffer);
impl IpcBuffer {
newtype_methods!(pub sys::seL4_IPCBuffer);
pub fn msg_regs(&self) -> &[Word] {
&self.inner().msg[..]
}
pub fn msg_regs_mut(&mut self) -> &mut [Word] {
&mut self.inner_mut().msg[..]
}
pub fn msg_bytes(&self) -> &[u8] {
let msg = &self.inner().msg;
let msg_ptr = msg as *const Word;
let size = mem::size_of_val(msg);
unsafe { slice::from_raw_parts(msg_ptr.cast(), size) }
}
pub fn msg_bytes_mut(&mut self) -> &mut [u8] {
let msg = &mut self.inner_mut().msg;
let msg_ptr = msg as *mut Word;
let size = mem::size_of_val(msg);
unsafe { slice::from_raw_parts_mut(msg_ptr.cast(), size) }
}
pub fn user_data(&self) -> Word {
self.inner().userData
}
pub fn set_user_data(&mut self, data: Word) {
self.inner_mut().userData = data;
}
pub fn caps_or_badges(&self) -> &[Word] {
&self.inner().caps_or_badges[..]
}
pub fn caps_or_badges_mut(&mut self) -> &mut [Word] {
&mut self.inner_mut().caps_or_badges[..]
}
pub fn recv_slot(&self) -> AbsoluteCPtr {
let inner = self.inner();
cap::CNode::from_bits(inner.receiveCNode).absolute_cptr_from_bits_with_depth(
inner.receiveIndex,
inner.receiveCNode.try_into().unwrap(),
)
}
pub fn set_recv_slot(&mut self, slot: &AbsoluteCPtr) {
let inner = self.inner_mut();
inner.receiveCNode = slot.root().bits();
inner.receiveIndex = slot.path().bits();
inner.receiveDepth = slot.path().depth().try_into().unwrap();
}
#[sel4_cfg(KERNEL_INVOCATION_REPORT_ERROR_IPC)]
pub fn debug_error_bytes(&self) -> &[u8] {
let start = u32_into_usize(sys::DEBUG_MESSAGE_START) * mem::size_of::<Word>();
let len = u32_into_usize(sys::DEBUG_MESSAGE_MAXLEN) * mem::size_of::<Word>();
let all_bytes = &self.msg_bytes()[start..][..len];
let n = all_bytes.iter().take_while(|b| **b != 0).count();
&all_bytes[..n]
}
#[sel4_cfg(KERNEL_INVOCATION_REPORT_ERROR_IPC)]
pub fn debug_error(&self) -> Result<&str, Utf8Error> {
str::from_utf8(self.debug_error_bytes())
}
}