1use std::{marker::PhantomData, ops::Deref};
5
6use rkyv::{bytecheck::CheckBytes, rancor};
7use xous_ipc::{XousDeserializer, XousValidator};
8
9use crate::WrongMessageTypeError;
10
11pub struct Owned<T> {
12 envelope: xous::MessageEnvelope,
13 _marker: PhantomData<T>,
14}
15
16impl<T> std::fmt::Debug for Owned<T>
17where
18 T: rkyv::Archive,
19 T::Archived: std::fmt::Debug,
20{
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 f.debug_tuple("Owned").field(&*self).finish()
23 }
24}
25
26impl<T> Owned<T>
27where
28 T: rkyv::Archive,
29 T::Archived: rkyv::Portable,
30{
31 pub fn new(envelope: xous::MessageEnvelope) -> Result<Self, rancor::Error>
32 where
33 T::Archived: for<'a> CheckBytes<XousValidator<'a>>,
34 {
35 match envelope.body.memory_message() {
36 Some(mem) => rkyv::api::low::access::<T::Archived, rancor::Error>(as_slice(mem))?,
37 None => rancor::fail!(WrongMessageTypeError),
38 };
39
40 Ok(Self { envelope, _marker: Default::default() })
41 }
42
43 pub fn new_move(envelope: xous::MessageEnvelope) -> Result<Self, rancor::Error>
44 where
45 T::Archived: for<'a> CheckBytes<XousValidator<'a>>,
46 {
47 match &envelope.body {
48 xous::Message::Move(mem) => rkyv::api::low::access::<T::Archived, rancor::Error>(as_slice(mem))?,
49 _ => rancor::fail!(WrongMessageTypeError),
50 };
51
52 Ok(Self { envelope, _marker: Default::default() })
53 }
54
55 #[inline]
56 pub fn deserialize(&self) -> Result<T, rancor::Error>
57 where
58 T::Archived: rkyv::Deserialize<T, XousDeserializer>,
59 {
60 rkyv::api::low::deserialize(self.access())
61 }
62
63 #[inline]
64 pub fn access(&self) -> &T::Archived { unsafe { rkyv::access_unchecked(self.as_slice()) } }
65}
66
67impl<T> Owned<T>
68where
69 T: rkyv::Archive,
70 T::Archived: rkyv::Portable,
71{
72 #[inline]
73 fn as_memory_message(&self) -> &xous::MemoryMessage {
74 match self.envelope.body.memory_message() {
75 Some(mem) => mem,
76 None => unreachable!("message was already checked in Owned::new"),
77 }
78 }
79
80 #[inline]
81 pub fn as_slice(&self) -> &[u8] { as_slice(self.as_memory_message()) }
82}
83
84impl<T> Deref for Owned<T>
85where
86 T: rkyv::Archive,
87 T::Archived: rkyv::Portable,
88{
89 type Target = T::Archived;
90
91 #[inline]
92 fn deref(&self) -> &Self::Target { self.access() }
93}
94
95#[inline]
96fn as_slice(mem: &xous::MemoryMessage) -> &[u8] {
97 let slice = mem.buf.as_slice();
98 let used = mem.offset.map_or(0, |v| v.get()).min(slice.len());
99 &slice[..used]
100}