1use std::{marker::PhantomData, ops::Deref};
5
6use rkyv::{bytecheck::CheckBytes, rancor};
7
8use crate::WrongMessageTypeError;
9use crate::{XousDeserializer, XousValidator};
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::<T, rancor::Error>(self.access())
61 }
62
63 #[inline]
64 pub fn access(&self) -> &T::Archived {
65 unsafe { rkyv::access_unchecked::<T::Archived>(self.as_slice()) }
67 }
68}
69
70impl<T> Owned<T>
71where
72 T: rkyv::Archive,
73 T::Archived: rkyv::Portable,
74{
75 #[inline]
76 fn as_memory_message(&self) -> &xous::MemoryMessage {
77 match self.envelope.body.memory_message() {
78 Some(mem) => mem,
79 None => unreachable!("message was already checked in Owned::new"),
80 }
81 }
82
83 #[inline]
84 pub fn as_slice(&self) -> &[u8] { as_slice(self.as_memory_message()) }
85}
86
87impl<T> Deref for Owned<T>
88where
89 T: rkyv::Archive,
90 T::Archived: rkyv::Portable,
91{
92 type Target = T::Archived;
93
94 #[inline]
95 fn deref(&self) -> &Self::Target { self.access() }
96}
97
98#[inline]
99fn as_slice(mem: &xous::MemoryMessage) -> &[u8] {
100 let slice = mem.buf.as_slice();
101 &slice[..crate::Buffer::message_len(mem)]
102}