1use crate::{Server, ServerContext};
5
6pub trait LendMutHandler<M: LendMut>
8where
9 Self: Server,
10{
11 fn handle(&mut self, msg: M, sender: xous::PID, context: &mut ServerContext<Self>) -> M::Response;
12}
13
14pub trait LendMut: crate::MessageId + From<SimpleMemoryMessage> + Into<SimpleMemoryMessage> {
16 type Response: LendMutResponse;
17}
18
19pub trait LendMutResponse {
20 fn from_usize_pair(arg1: usize, arg2: usize) -> Self;
21 fn to_usize_pair(self) -> (usize, usize);
22}
23
24impl LendMutResponse for () {
25 fn from_usize_pair(_arg1: usize, _arg2: usize) {}
26
27 fn to_usize_pair(self) -> (usize, usize) { (0, 0) }
28}
29
30impl LendMutResponse for usize {
31 fn from_usize_pair(arg1: usize, _arg2: usize) -> usize { arg1 }
32
33 fn to_usize_pair(self) -> (usize, usize) { (self, 0) }
34}
35
36impl<T1: From<usize> + Into<usize>, T2: From<usize> + Into<usize>> LendMutResponse for Result<T1, T2> {
37 fn from_usize_pair(arg1: usize, arg2: usize) -> Self {
38 if arg1 == 0 {
39 Ok(arg2.into())
40 } else {
41 Err(arg2.into())
42 }
43 }
44
45 fn to_usize_pair(self) -> (usize, usize) {
46 match self {
47 Ok(o) => (0, o.into()),
48 Err(e) => (1, e.into()),
49 }
50 }
51}
52
53pub struct SimpleMemoryMessage {
55 pub buf: xous::MemoryRange,
58 pub arg1: usize,
59 pub arg2: usize,
60}
61
62impl From<&xous::MemoryMessage> for SimpleMemoryMessage {
63 fn from(value: &xous::MemoryMessage) -> Self {
64 Self {
65 buf: value.buf,
66 arg1: value.offset.map(|v| v.get()).unwrap_or_default(),
67 arg2: value.valid.map(|v| v.get()).unwrap_or_default(),
68 }
69 }
70}
71
72pub fn handle_lend_mut<M: LendMut, S: LendMutHandler<M>>(
74 handler: &mut S,
75 mut raw: xous::MessageEnvelope,
76 context: &mut ServerContext<S>,
77) {
78 let xous::Message::MutableBorrow(mem) = &mut raw.body else {
79 log::warn!("invalid message: {raw:?}");
80 return;
81 };
82
83 let msg = M::from(SimpleMemoryMessage::from(&*mem));
84 let (arg1, arg2) = handler.handle(msg, raw.sender.pid().unwrap(), context).to_usize_pair();
85 mem.offset = xous::MemoryAddress::new(arg1);
86 mem.valid = xous::MemoryAddress::new(arg2);
87}
88
89pub fn lend_mut<M: LendMut>(cid: xous::CID, msg: M) -> M::Response {
91 let msg: SimpleMemoryMessage = msg.into();
92 let result = xous::send_message(
93 cid,
94 xous::Message::MutableBorrow(xous::MemoryMessage {
95 id: M::ID,
96 buf: msg.buf,
97 offset: xous::MemoryAddress::new(msg.arg1),
98 valid: xous::MemoryAddress::new(msg.arg2),
99 }),
100 );
101 match result {
102 Ok(xous::Result::MemoryReturned(_range, arg1, arg2)) => M::Response::from_usize_pair(
103 arg1.map(|v| v.get()).unwrap_or_default(),
104 arg2.map(|v| v.get()).unwrap_or_default(),
105 ),
106 _ => panic!("Unexpected return from send_message: {result:?}"),
107 }
108}