1use rkyv::{Deserialize, Portable};
5use xous::{
6 map_memory, send_message, try_send_message, unmap_memory, Error, MemoryAddress, MemoryFlags,
7 MemoryMessage, MemoryRange, MemorySize, Message, Result, CID,
8};
9
10use crate::rkyv_utils::{
11 decode, serialize_into, serialized_size, SizeOfSerializer, XousDeserializer, XousSerializer,
12 XousValidator,
13};
14
15#[derive(Debug)]
16pub struct Buffer {
17 pages: MemoryRange,
18 used: usize,
19 should_drop: bool,
20}
21
22impl Buffer {
23 pub(crate) fn new(len: usize) -> core::result::Result<Self, Error> {
24 let len = core::cmp::max(len.next_multiple_of(0x1000), 0x1000);
25 let pages = map_memory(None, None, len, MemoryFlags::W)?;
26 Ok(Buffer { pages, used: 0, should_drop: true })
27 }
28
29 fn bytes(&self) -> &[u8] {
30 unsafe { core::slice::from_raw_parts(self.pages.as_ptr(), self.pages.len()) }
33 }
34
35 fn bytes_mut(&mut self) -> &mut [u8] {
36 unsafe { core::slice::from_raw_parts_mut(self.pages.as_mut_ptr(), self.pages.len()) }
38 }
39
40 fn len_fields(len: usize) -> (Option<MemoryAddress>, Option<MemorySize>) { (None, MemorySize::new(len)) }
43
44 pub(crate) fn message_len(mem: &MemoryMessage) -> usize {
46 mem.valid.map_or(0, |v| v.get()).min(mem.buf.len())
47 }
48
49 fn message(&self, id: u32) -> MemoryMessage {
51 let (offset, valid) = Self::len_fields(self.used);
52 MemoryMessage { id: id as usize, buf: self.pages, offset, valid }
53 }
54
55 fn into_inner(mut self) -> core::result::Result<(MemoryRange, usize), Error> {
59 if self.should_drop {
60 self.should_drop = false;
61 Ok((self.pages, self.used))
62 } else {
63 Err(Error::ShareViolation)
64 }
65 }
66
67 pub(crate) fn deserialize<T>(mem: &MemoryMessage) -> core::result::Result<T, rkyv::rancor::Error>
69 where
70 T: rkyv::Archive,
71 T::Archived: Portable
72 + for<'a> rkyv::bytecheck::CheckBytes<XousValidator<'a>>
73 + Deserialize<T, XousDeserializer>,
74 {
75 decode(&mem.buf.as_slice::<u8>()[..Self::message_len(mem)])
76 }
77
78 pub(crate) fn reply<T>(mem: &mut MemoryMessage, src: &T) -> core::result::Result<(), rkyv::rancor::Error>
81 where
82 T: for<'a, 'b> rkyv::Serialize<XousSerializer<'a, 'b>>,
83 {
84 let dst = unsafe { core::slice::from_raw_parts_mut(mem.buf.as_mut_ptr(), mem.buf.len()) };
86 let used = serialize_into(dst, src)?;
87 (mem.offset, mem.valid) = Self::len_fields(used);
88 Ok(())
89 }
90
91 pub(crate) fn reply_move<T>(mem: &mut MemoryMessage, src: &T) -> core::result::Result<(), crate::Error>
97 where
98 T: for<'a, 'b> rkyv::Serialize<XousSerializer<'a, 'b>>
99 + for<'a> rkyv::Serialize<SizeOfSerializer<'a>>,
100 {
101 let existing = mem.buf;
102 let size = serialized_size(src)?;
103 let needed = core::cmp::max(size.next_multiple_of(0x1000), 0x1000);
104
105 let (reply, used) = if cfg!(keyos) && existing.len() >= needed {
108 let reply = existing.subrange(0, needed).expect("page-aligned subrange of a mapped buffer");
109 let dst = unsafe { core::slice::from_raw_parts_mut(reply.as_mut_ptr(), reply.len()) };
111 (reply, serialize_into(dst, src)?)
112 } else {
113 let mut buf = Self::new(size)?;
115 let used = serialize_into(buf.bytes_mut(), src)?;
116 (buf.into_inner().expect("freshly mapped buffer is ownable").0, used)
117 };
118 mem.buf = reply;
119 (mem.offset, mem.valid) = Self::len_fields(used);
120
121 if reply.as_ptr() == existing.as_ptr() {
124 let tail_len = existing.len() - reply.len();
125 if tail_len > 0 {
126 let tail =
127 existing.subrange(reply.len(), tail_len).expect("tail subrange of a mapped buffer");
128 unmap_memory(tail).expect("unmap reply tail");
129 }
130 } else {
131 unmap_memory(existing).expect("unmap moved-in buffer");
132 }
133 Ok(())
134 }
135
136 pub(crate) fn lend_mut(&mut self, connection: CID, id: u32) -> core::result::Result<Result, Error> {
138 let msg = self.message(id);
139 let result = send_message(connection, Message::MutableBorrow(msg));
140 if let Ok(Result::MemoryReturned(_range, _offset, valid)) = result {
141 self.used = valid.map_or(0, |v| v.get()).min(self.pages.len());
142 }
143
144 result
145 }
146
147 pub(crate) fn blocking_move(&mut self, connection: CID, id: u32) -> core::result::Result<Result, Error> {
152 let msg = self.message(id);
153 let result = send_message(connection, Message::BlockingMove(msg))?;
157 if let Result::MemoryReturned(range, _offset, valid) = result {
158 self.pages = range;
159 self.used = valid.map_or(0, |v| v.get()).min(range.len());
160 self.should_drop = true;
161 }
162 Ok(result)
163 }
164
165 pub fn send(mut self, connection: CID, id: u32) -> core::result::Result<Result, Error> {
166 let msg = self.message(id);
167 let result = send_message(connection, Message::Move(msg))?;
168
169 self.should_drop = false;
171 Ok(result)
172 }
173
174 pub(crate) fn send_nowait(mut self, connection: CID, id: u32) -> core::result::Result<Result, Error> {
175 let msg = self.message(id);
176 let result = try_send_message(connection, Message::Move(msg))?;
177
178 self.should_drop = false;
180 Ok(result)
181 }
182
183 pub fn from_bytes(bytes: &[u8]) -> core::result::Result<Self, Error> {
186 let mut buf = Self::new(bytes.len())?;
187 buf.bytes_mut()[..bytes.len()].copy_from_slice(bytes);
188 buf.used = bytes.len();
189 Ok(buf)
190 }
191
192 pub(crate) fn into_buf<T>(src: &T) -> core::result::Result<Self, crate::Error>
193 where
194 T: for<'a, 'b> rkyv::Serialize<XousSerializer<'a, 'b>>
195 + for<'a> rkyv::Serialize<SizeOfSerializer<'a>>,
196 {
197 let mut buf = Self::new(serialized_size(src)?)?;
198 buf.used = serialize_into(buf.bytes_mut(), src)?;
199 Ok(buf)
200 }
201
202 #[inline]
204 pub(crate) fn to_original<T>(&self) -> core::result::Result<T, rkyv::rancor::Error>
205 where
206 T: rkyv::Archive,
207 T::Archived: Portable
208 + for<'a> rkyv::bytecheck::CheckBytes<XousValidator<'a>>
209 + Deserialize<T, XousDeserializer>,
210 {
211 decode(&self.bytes()[..self.used])
212 }
213}
214
215impl Drop for Buffer {
216 fn drop(&mut self) {
217 if self.should_drop {
218 unmap_memory(self.pages).expect("Buffer: failed to drop memory");
219 }
220 }
221}