server/deferred/
lend_mut.rs1use xous::MessageSender;
5
6use crate::{LendMut, LendMutResponse, Server, ServerContext, SimpleMemoryMessage};
7pub trait DeferredLendMutHandler<M>
9where
10 M: LendMut,
11 Self: Server,
12{
13 fn handle(&mut self, msg: DeferredLendMut<M>, context: &mut ServerContext<Self>);
14 fn default_response() -> M::Response;
15}
16
17#[derive(Debug)]
21pub struct DeferredLendMut<M: LendMut> {
22 sender: MessageSender,
23 body: Option<M>,
24 response: Option<M::Response>,
25}
26
27impl<M: LendMut> DeferredLendMut<M> {
28 pub(crate) fn new(mut envelope: xous::MessageEnvelope, response: M::Response) -> Option<Self> {
29 let sender = envelope.sender;
30 let body = if let xous::Message::MutableBorrow(mem) = &mut envelope.body {
31 M::from(SimpleMemoryMessage::from(&*mem))
32 } else {
33 log::warn!("invalid message: {envelope:?}");
34 return None;
35 };
36 #[allow(clippy::forget_non_drop)]
38 core::mem::forget(envelope);
39 Some(Self { sender, body: Some(body), response: Some(response) })
40 }
41
42 pub fn pid(&self) -> xous::PID { self.sender.pid().unwrap() }
44
45 pub fn body(&self) -> &M { self.body.as_ref().unwrap() }
47
48 pub fn body_mut(&mut self) -> &mut M { self.body.as_mut().unwrap() }
50
51 pub fn set_response(&mut self, response: M::Response) { self.response = Some(response) }
53}
54
55impl<M: LendMut> Drop for DeferredLendMut<M> {
56 fn drop(&mut self) {
57 let simple: SimpleMemoryMessage = self.body.take().unwrap().into();
58 let (arg1, arg2) = self.response.take().unwrap().to_usize_pair();
59 xous::syscall::return_memory_offset_valid(
60 self.sender,
61 simple.buf,
62 xous::MemoryAddress::new(arg1),
63 xous::MemoryAddress::new(arg2),
64 )
65 .expect("couldn't return memory")
66 }
67}
68
69pub fn handle_deferred_lend_mut<M, S>(
71 handler: &mut S,
72 raw: xous::MessageEnvelope,
73 context: &mut ServerContext<S>,
74) where
75 M: LendMut + 'static,
76 S: Server + DeferredLendMutHandler<M>,
77{
78 let Some(deferred) = DeferredLendMut::new(raw, S::default_response()) else { return };
79 handler.handle(deferred, context);
80}