1use std::any::type_name;
7
8use rkyv::{
9 bytecheck::CheckBytes,
10 rancor::{self, Source as _},
11};
12use whence::WhenceExt;
13
14use crate::{AsyncMessageInit, Error, Server, ServerContext, WrongMessageTypeError};
15use crate::{SizeOfSerializer, XousDeserializer, XousSerializer, XousValidator};
16
17pub trait BlockingArchive
21where
22 Self: ArchiveCodec,
23 Self: crate::MessageId,
24 <Self::Response as rkyv::Archive>::Archived:
25 rkyv::Deserialize<Self::Response, XousDeserializer> + for<'a> CheckBytes<XousValidator<'a>>,
26{
27 type Response: ArchiveCodec;
29}
30
31pub trait ArchiveCodec
33where
34 Self: Sized
35 + rkyv::Archive
36 + for<'a, 'b> rkyv::Serialize<XousSerializer<'a, 'b>>
37 + for<'a> rkyv::Serialize<SizeOfSerializer<'a>>,
38 Self::Archived: rkyv::Portable,
39{
40}
41
42impl<T> ArchiveCodec for T
43where
44 T: Sized
45 + rkyv::Archive
46 + for<'a, 'b> rkyv::Serialize<XousSerializer<'a, 'b>>
47 + for<'a> rkyv::Serialize<SizeOfSerializer<'a>>,
48 T::Archived: rkyv::Portable,
49{
50}
51
52pub trait BlockingArchiveHandler<M>
56where
57 M: BlockingArchive,
58 Self: Server,
59{
60 fn handle(&mut self, msg: M, sender: xous::PID, context: &mut ServerContext<Self>) -> M::Response;
62}
63
64pub trait BlockingArchiveAsyncHandler<M>
66where
67 M: BlockingArchive,
68 Self: Server,
69{
70 fn handle(&mut self, request: ArchiveRequest<M>, context: &mut ServerContext<Self>);
72 fn default_response() -> M::Response;
74}
75
76impl<T, M> BlockingArchiveAsyncHandler<M> for T
78where
79 M: BlockingArchive,
80 T: BlockingArchiveHandler<M>,
81{
82 fn handle(&mut self, request: ArchiveRequest<M>, context: &mut ServerContext<Self>) {
83 let ArchiveRequest { message, response: request } = request;
84 let response = <Self as BlockingArchiveHandler<M>>::handle(self, message, request.pid(), context);
85 if let Err(e) = request.respond(response) {
86 log::warn!("failed to respond archive {e:?}");
87 }
88 }
89
90 fn default_response() -> <M as BlockingArchive>::Response {
91 unreachable!("default value not required in sync handler")
92 }
93}
94
95pub trait ArchiveResponseHandler<R>
97where
98 Self: Server,
99 R: ArchiveCodec,
100{
101 fn handle_response(&mut self, response: R, sender: xous::PID, context: &mut ServerContext<Self>);
103}
104
105#[derive(Debug)]
109pub struct ArchiveRequest<M: BlockingArchive> {
110 pub message: M,
111 pub response: ArchiveResponse<M::Response>,
112}
113
114#[derive(Debug)]
116pub struct ArchiveResponse<R: ArchiveCodec> {
117 responder: Option<Responder>,
118 pid: xous::PID,
119 default: fn() -> R,
120}
121
122impl<R: ArchiveCodec> ArchiveResponse<R> {
123 pub fn pid(&self) -> xous::PID { self.pid }
125
126 pub fn respond(mut self, response: R) -> whence::Result<(), Error> {
128 let responder = self.responder.take().unwrap();
129 responder.respond(&response)
130 }
131
132 pub fn set_response(&mut self, f: fn() -> R) { self.default = f; }
135}
136
137impl<R: ArchiveCodec> Drop for ArchiveResponse<R> {
139 fn drop(&mut self) {
140 if let Some(responder) = self.responder.take() {
141 let default = (self.default)();
142 responder.respond(&default).ok();
143 }
144 }
145}
146
147pub fn send_blocking_archive<M>(cid: xous::CID, msg: M) -> M::Response
151where
152 M: BlockingArchive,
153{
154 try_send_blocking_archive(cid, msg).unwrap()
155}
156
157pub fn try_send_blocking_archive<M>(cid: xous::CID, msg: M) -> whence::Result<M::Response, Error>
159where
160 M: BlockingArchive,
161{
162 let mut buf = crate::Buffer::into_buf(&msg).whence()?;
163 buf.blocking_move(cid, M::ID as u32).whence()?;
164 buf.to_original().whence()
165}
166
167pub fn handle_blocking_archive_message<M, S>(
169 handler: &mut S,
170 raw: xous::MessageEnvelope,
171 context: &mut ServerContext<S>,
172) where
173 M: BlockingArchive,
174 S: BlockingArchiveAsyncHandler<M>,
175 <M as rkyv::Archive>::Archived:
176 rkyv::Deserialize<M, XousDeserializer> + for<'a> CheckBytes<XousValidator<'a>>,
177{
178 let pid = raw.sender.pid().unwrap();
179 if let Err(e) = try_handle_blocking_archive_message(handler, raw, context) {
180 log::warn!("BlockingArchive handle error (PID {pid}) for {}: {e}", type_name::<M>());
181 }
182}
183
184fn try_handle_blocking_archive_message<M, S>(
185 handler: &mut S,
186 mut raw: xous::MessageEnvelope,
187 context: &mut ServerContext<S>,
188) -> whence::Result<(), Error>
189where
190 M: BlockingArchive,
191 S: BlockingArchiveAsyncHandler<M>,
192 <M as rkyv::Archive>::Archived:
193 rkyv::Deserialize<M, XousDeserializer> + for<'a> CheckBytes<XousValidator<'a>>,
194{
195 let pid = raw.sender.pid().unwrap();
196
197 match &mut raw.body {
198 xous::Message::BlockingMove(mem) => {
199 let message: M = crate::Buffer::deserialize::<M>(mem).whence()?;
201 let request =
202 ArchiveResponse { responder: Some(Responder::Sync(raw)), pid, default: S::default_response };
203 let request = ArchiveRequest { message, response: request };
204 handler.handle(request, context);
205 Ok(())
206 }
207 xous::Message::Move(mem) => {
208 let init: AsyncMessageInit<M> = crate::Buffer::deserialize(mem).whence()?;
210 let request = ArchiveResponse {
211 responder: Some(Responder::Async { cid: init.cid, msg_id: init.msg_id }),
212 pid,
213 default: S::default_response,
214 };
215 let request = ArchiveRequest { message: init.msg, response: request };
216 handler.handle(request, context);
217 Ok(())
218 }
219 _ => Err(rancor::Error::new(WrongMessageTypeError)).whence(),
220 }
221}
222pub fn decode_archive_async_response<M>(raw: xous::MessageEnvelope) -> M
224where
225 M: ArchiveCodec,
226 <M as rkyv::Archive>::Archived:
227 rkyv::Deserialize<M, XousDeserializer> + for<'a> CheckBytes<XousValidator<'a>>,
228{
229 try_decode_archive_async_response(raw).unwrap()
230}
231
232pub fn try_decode_archive_async_response<M>(raw: xous::MessageEnvelope) -> whence::Result<M, Error>
233where
234 M: ArchiveCodec,
235 <M as rkyv::Archive>::Archived:
236 rkyv::Deserialize<M, XousDeserializer> + for<'a> CheckBytes<XousValidator<'a>>,
237{
238 crate::r#move::decode_move::<M>(&raw).whence()
239}
240
241#[derive(Debug)]
244enum Responder {
245 Sync(xous::MessageEnvelope),
247 Async { cid: xous::CID, msg_id: xous::MessageId },
249}
250
251impl Responder {
252 fn respond<R>(self, response: &R) -> whence::Result<(), Error>
253 where
254 R: ArchiveCodec,
255 {
256 match self {
257 Responder::Sync(mut envelope) => {
258 let mem = envelope.body.memory_message_mut().expect("blocking move carries memory");
259 crate::Buffer::reply_move(mem, response).whence()
260 }
261 Responder::Async { cid, msg_id } => {
262 let _disconnect = defer::defer(|| {
263 xous::disconnect(cid).ok();
264 });
265 crate::Buffer::into_buf(response).whence()?.send_nowait(cid, msg_id as u32).whence()?;
266 Ok(())
267 }
268 }
269 }
270}