1use std::any::type_name;
7
8use rkyv::rancor::{self, Source as _};
9use whence::WhenceExt;
10
11use crate::{utils, AsyncMessageInit, Error, Server, ServerContext, WrongMessageTypeError};
12
13pub trait BlockingScalar
17where
18 Self: ScalarCodec,
19 Self: crate::MessageId,
20{
21 type Response: ScalarCodec;
23}
24
25pub trait ScalarCodec
27where
28 Self: FromScalar<4> + AsScalar<4>,
29{
30}
31
32impl<T> ScalarCodec for T where T: FromScalar<4> + AsScalar<4> {}
33
34pub trait BlockingScalarHandler<M>
38where
39 M: BlockingScalar,
40 Self: Server,
41{
42 fn handle(&mut self, msg: M, sender: xous::PID, context: &mut ServerContext<Self>) -> M::Response;
44}
45
46pub trait BlockingScalarAsyncHandler<M>
48where
49 M: BlockingScalar,
50 Self: Server,
51{
52 fn handle(&mut self, request: BlockingScalarRequest<M>, context: &mut ServerContext<Self>);
54 fn default_response() -> M::Response;
56}
57
58impl<T, M> BlockingScalarAsyncHandler<M> for T
60where
61 M: BlockingScalar,
62 T: BlockingScalarHandler<M>,
63{
64 fn handle(&mut self, request: BlockingScalarRequest<M>, context: &mut ServerContext<Self>) {
65 let BlockingScalarRequest { message, response: request } = request;
66 let response = <Self as BlockingScalarHandler<M>>::handle(self, message, request.pid(), context);
67 if let Err(e) = request.respond(response) {
68 log::warn!("failed to respond scalar {e:?}");
69 }
70 }
71
72 fn default_response() -> <M as BlockingScalar>::Response {
73 unreachable!("default value not required in sync handler")
74 }
75}
76
77pub trait BlockingScalarResponseHandler<R>
79where
80 Self: Server,
81 R: ScalarCodec,
82{
83 fn handle_response(&mut self, response: R, sender: xous::PID, context: &mut ServerContext<Self>);
85}
86
87#[derive(Debug)]
91pub struct BlockingScalarRequest<M: BlockingScalar> {
92 pub message: M,
93 pub response: BlockingScalarResponse<M::Response>,
94}
95
96#[derive(Debug)]
98pub struct BlockingScalarResponse<R: ScalarCodec> {
99 responder: Option<Responder>,
100 pid: xous::PID,
101 default: fn() -> R,
102 response: Option<R>,
103}
104
105impl<R: ScalarCodec> BlockingScalarResponse<R> {
106 pub fn pid(&self) -> xous::PID { self.pid }
108
109 pub fn respond(mut self, response: R) -> whence::Result<(), xous::Error> {
111 let responder = self.responder.take().unwrap();
112 responder.respond(response)
113 }
114
115 pub fn set_response(&mut self, response: R) { self.response = Some(response) }
118}
119
120impl<R: ScalarCodec> Drop for BlockingScalarResponse<R> {
122 fn drop(&mut self) {
123 if let Some(responder) = self.responder.take() {
124 let default = self.response.take().unwrap_or_else(self.default);
125 responder.respond(default).ok();
126 }
127 }
128}
129
130pub fn send_blocking_scalar<M>(cid: xous::CID, msg: M) -> M::Response
134where
135 M: BlockingScalar,
136{
137 try_send_blocking_scalar(cid, msg).unwrap()
138}
139
140pub fn try_send_blocking_scalar<M>(cid: xous::CID, msg: M) -> whence::Result<M::Response, xous::Error>
142where
143 M: BlockingScalar,
144{
145 let msg = xous::Message::BlockingScalar(utils::scalar_to_message(&msg, M::ID));
146 let result = xous::send_message(cid, msg).whence()?;
147 match result {
148 xous::Result::Scalar5(arg1, arg2, arg3, arg4, _) => {
149 Ok(M::Response::from_scalar([arg1 as u32, arg2 as u32, arg3 as u32, arg4 as u32]))
150 }
151 unexpected => {
152 log::error!(
153 "unexpected result for message {} (ID {}): {:?}",
154 type_name::<M>(),
155 M::ID,
156 unexpected
157 );
158 Err(xous::Error::InternalError).whence()?
159 }
160 }
161}
162
163pub fn send_scalar_async<M>(cid: xous::CID, msg: M, sid: xous::SID) -> xous::MessageId
166where
167 M: BlockingScalar,
168{
169 try_send_scalar_async(cid, msg, sid).unwrap()
170}
171
172pub fn try_send_scalar_async<M>(
175 cid: xous::CID,
176 msg: M,
177 sid: xous::SID,
178) -> whence::Result<xous::MessageId, crate::Error>
179where
180 M: BlockingScalar,
181{
182 let msg_id = crate::next_dynamic_message_id();
183 let pid = xous::get_remote_pid(cid).whence()?;
184 let cid_remote = xous::connect_for_process(pid, sid).whence()?;
185 xous::allow_messages_on_connection(pid, cid_remote, msg_id..(msg_id + 1)).whence()?;
186 AsyncMessageInit { cid: cid_remote, msg_id, msg }.send_scalar(cid)?;
187 Ok(msg_id)
188}
189
190pub fn handle_blocking_scalar_message<M, S>(
192 handler: &mut S,
193 raw: xous::MessageEnvelope,
194 context: &mut ServerContext<S>,
195) where
196 M: BlockingScalar,
197 S: BlockingScalarAsyncHandler<M>,
198{
199 let pid = raw.sender.pid().unwrap();
200 if let Err(e) = try_handle_blocking_scalar_message(pid, handler, raw, context) {
201 log::warn!("blocking scalar handle error (PID {pid}) for {}: {e}", type_name::<M>());
202 }
203}
204
205fn try_handle_blocking_scalar_message<M, S>(
206 pid: xous::PID,
207 handler: &mut S,
208 mut raw: xous::MessageEnvelope,
209 context: &mut ServerContext<S>,
210) -> whence::Result<(), Error>
211where
212 M: BlockingScalar,
213 S: BlockingScalarAsyncHandler<M>,
214{
215 match &mut raw.body {
216 xous::Message::BlockingScalar(scalar) => {
217 let message = utils::scalar_from_message::<M>(scalar);
219 let request = BlockingScalarResponse {
220 responder: Some(Responder::Sync(raw)),
221 pid,
222 default: S::default_response,
223 response: None,
224 };
225 let request = BlockingScalarRequest { message, response: request };
226 handler.handle(request, context);
227 Ok(())
228 }
229 xous::Message::Move(mem) => {
230 let buf = unsafe { xous_ipc::Buffer::from_memory_message(mem) };
232 let init: AsyncMessageInit<[u32; 4]> = buf.to_original().whence()?;
233 let AsyncMessageInit { cid, msg_id, msg } = init;
234 let request = BlockingScalarResponse {
235 responder: Some(Responder::Async { cid, msg_id }),
236 pid,
237 default: S::default_response,
238 response: None,
239 };
240 let request = BlockingScalarRequest { message: M::from_scalar(msg), response: request };
241 handler.handle(request, context);
242 Ok(())
243 }
244 _ => Err(rancor::Error::new(WrongMessageTypeError)).whence(),
245 }
246}
247
248pub fn decode_scalar_async_response<R>(raw: xous::MessageEnvelope) -> R
250where
251 R: ScalarCodec,
252{
253 try_decode_scalar_async_response(raw).unwrap()
254}
255
256pub fn try_decode_scalar_async_response<R>(mut raw: xous::MessageEnvelope) -> whence::Result<R, crate::Error>
258where
259 R: ScalarCodec,
260{
261 let scalar = utils::extract_scalar_message(&mut raw).whence()?;
262 Ok(R::from_scalar(scalar))
263}
264
265pub trait Scalar: ScalarCodec + crate::MessageId {
269 fn to_message(&self) -> xous::ScalarMessage
270 where
271 Self: Sized,
272 {
273 utils::scalar_to_message(self, Self::ID)
274 }
275}
276
277pub trait ScalarHandler<M>
279where
280 M: Scalar,
281 Self: Server,
282{
283 fn handle(&mut self, msg: M, sender: xous::PID, context: &mut ServerContext<Self>);
285}
286
287pub fn send_scalar<M>(cid: xous::CID, msg: M)
291where
292 M: Scalar,
293{
294 try_send_scalar(cid, msg).unwrap()
295}
296
297pub fn try_send_scalar<M>(cid: xous::CID, msg: M) -> whence::Result<(), xous::Error>
301where
302 M: Scalar,
303{
304 let msg = xous::Message::Scalar(msg.to_message());
305 xous::send_message(cid, msg).whence()?;
306 Ok(())
307}
308
309pub fn send_scalar_nowait<M>(cid: xous::CID, msg: M) -> whence::Result<(), xous::Error>
312where
313 M: Scalar,
314{
315 let msg = xous::Message::Scalar(msg.to_message());
316 xous::try_send_message(cid, msg).whence()?;
317 Ok(())
318}
319
320pub fn handle_scalar_message<M, S>(
322 handler: &mut S,
323 mut raw: xous::MessageEnvelope,
324 context: &mut ServerContext<S>,
325) where
326 M: Scalar,
327 S: ScalarHandler<M>,
328{
329 let pid = raw.sender.pid().unwrap();
330
331 match &mut raw.body {
332 xous::Message::Scalar(scalar) => {
333 let message = utils::scalar_from_message(scalar);
334 handler.handle(message, pid, context);
335 }
336 _ => {
337 log::error!("invalid Scalar message {} (ID {}) from PID {pid}: {raw:?}", type_name::<M>(), M::ID,);
338 }
339 }
340}
341
342pub(crate) fn scalar_async_response_handler<M, S>(
346 handler: &mut S,
347 raw: xous::MessageEnvelope,
348 context: &mut ServerContext<S>,
349) where
350 M: BlockingScalar,
351 S: BlockingScalarResponseHandler<M::Response>,
352{
353 let msg_id = raw.id();
354 let sender = raw.sender.pid().unwrap();
355
356 match try_decode_scalar_async_response(raw) {
357 Ok(response) => {
358 handler.handle_response(response, sender, context);
359 }
360 Err(e) => log::warn!("invalid async scalar response {e}"),
361 }
362
363 context.remove_handler(msg_id);
364}
365
366#[derive(Debug)]
367enum Responder {
368 Sync(xous::MessageEnvelope),
370 Async { cid: xous::CID, msg_id: xous::MessageId },
372}
373
374impl Responder {
375 fn respond<R>(self, response: R) -> whence::Result<(), xous::Error>
376 where
377 R: ScalarCodec,
378 {
379 match self {
380 Responder::Sync(envelope) => {
381 let [arg1, arg2, arg3, arg4] = response.as_scalar().map(|a| a as usize);
382 xous::return_scalar5(envelope.sender, arg1, arg2, arg3, arg4, 0).whence()
383 }
384 Responder::Async { cid, msg_id } => {
385 let _disconnect = defer::defer(|| {
386 xous::disconnect(cid).ok();
387 });
388 let msg = utils::scalar_to_message(&response, msg_id);
389 xous::try_send_message(cid, xous::Message::Scalar(msg)).whence()?;
390 Ok(())
391 }
392 }
393 }
394}
395
396pub use codec::*;
399
400mod codec {
401 use xous::MemoryRange;
402
403 pub trait FromScalar<const N: usize> {
406 fn from_scalar(value: [u32; N]) -> Self;
407 }
408
409 pub trait AsScalar<const N: usize> {
410 fn as_scalar(&self) -> [u32; N];
411 }
412
413 impl<T: FromScalar<3>> FromScalar<4> for T {
416 fn from_scalar(value: [u32; 4]) -> Self { Self::from_scalar([value[0], value[1], value[2]]) }
417 }
418
419 impl<T: AsScalar<3>> AsScalar<4> for T {
420 fn as_scalar(&self) -> [u32; 4] {
421 let s = Self::as_scalar(self);
422 [s[0], s[1], s[2], 0]
423 }
424 }
425
426 impl<T: FromScalar<2>> FromScalar<3> for T {
427 fn from_scalar(value: [u32; 3]) -> Self { Self::from_scalar([value[0], value[1]]) }
428 }
429
430 impl<T: AsScalar<2>> AsScalar<3> for T {
431 fn as_scalar(&self) -> [u32; 3] {
432 let s = Self::as_scalar(self);
433 [s[0], s[1], 0]
434 }
435 }
436
437 impl<T: FromScalar<1>> FromScalar<2> for T {
438 fn from_scalar(value: [u32; 2]) -> Self { Self::from_scalar([value[0]]) }
439 }
440
441 impl<T: AsScalar<1>> AsScalar<2> for T {
442 fn as_scalar(&self) -> [u32; 2] {
443 let s = Self::as_scalar(self);
444 [s[0], 0]
445 }
446 }
447
448 impl FromScalar<1> for () {
451 fn from_scalar(_value: [u32; 1]) -> Self {}
452 }
453
454 impl AsScalar<1> for () {
455 fn as_scalar(&self) -> [u32; 1] { [0] }
456 }
457
458 impl FromScalar<1> for usize {
459 fn from_scalar(value: [u32; 1]) -> Self { value[0] as usize }
460 }
461
462 impl AsScalar<1> for usize {
463 fn as_scalar(&self) -> [u32; 1] { [*self as u32] }
464 }
465
466 impl FromScalar<1> for i32 {
467 fn from_scalar(value: [u32; 1]) -> Self { value[0] as i32 }
468 }
469
470 impl AsScalar<1> for i32 {
471 fn as_scalar(&self) -> [u32; 1] { [*self as u32] }
472 }
473
474 impl FromScalar<1> for u8 {
475 fn from_scalar(value: [u32; 1]) -> Self { value[0] as u8 }
476 }
477
478 impl AsScalar<1> for u8 {
479 fn as_scalar(&self) -> [u32; 1] { [*self as u32] }
480 }
481
482 impl FromScalar<1> for u16 {
483 fn from_scalar(value: [u32; 1]) -> Self { value[0] as u16 }
484 }
485
486 impl AsScalar<1> for u16 {
487 fn as_scalar(&self) -> [u32; 1] { [*self as u32] }
488 }
489
490 impl FromScalar<1> for u32 {
491 fn from_scalar(value: [u32; 1]) -> Self { value[0] }
492 }
493
494 impl AsScalar<1> for u32 {
495 fn as_scalar(&self) -> [u32; 1] { [*self] }
496 }
497
498 impl FromScalar<2> for u64 {
499 fn from_scalar(value: [u32; 2]) -> Self { (value[0] as u64) | ((value[1] as u64) << 32) }
500 }
501
502 impl AsScalar<2> for u64 {
503 fn as_scalar(&self) -> [u32; 2] { [*self as u32, (*self >> 32) as u32] }
504 }
505
506 impl FromScalar<1> for bool {
507 fn from_scalar(value: [u32; 1]) -> Self { value[0] != 0 }
508 }
509
510 impl AsScalar<1> for bool {
511 fn as_scalar(&self) -> [u32; 1] { [if *self { 1 } else { 0 }] }
512 }
513
514 impl FromScalar<1> for xous::PID {
517 fn from_scalar(value: [u32; 1]) -> Self { xous::PID::new(value[0].try_into().unwrap()).unwrap() }
518 }
519
520 impl AsScalar<1> for xous::PID {
521 fn as_scalar(&self) -> [u32; 1] { [self.get() as u32] }
522 }
523
524 impl AsScalar<4> for xous::SID {
525 fn as_scalar(&self) -> [u32; 4] {
526 let s = self.to_u32();
527 [s.0, s.1, s.2, s.3]
528 }
529 }
530
531 impl FromScalar<4> for xous::SID {
532 fn from_scalar(value: [u32; 4]) -> Self { Self::from_u32(value[0], value[1], value[2], value[3]) }
533 }
534
535 impl FromScalar<4> for xous::AppId {
536 fn from_scalar(value: [u32; 4]) -> Self { value.into() }
537 }
538
539 impl AsScalar<4> for xous::AppId {
540 fn as_scalar(&self) -> [u32; 4] { self.into() }
541 }
542
543 #[cfg(not(keyos))]
546 impl AsScalar<3> for MemoryRange {
547 fn as_scalar(&self) -> [u32; 3] {
548 let ptr = self.as_ptr() as usize;
549 [ptr as _, (ptr >> 32) as _, self.len() as _]
550 }
551 }
552
553 #[cfg(not(keyos))]
554 impl FromScalar<3> for MemoryRange {
555 fn from_scalar(value: [u32; 3]) -> Self {
556 let ptr = (value[0] as usize) | ((value[1] as usize) << 32);
557 unsafe { MemoryRange::new(ptr, value[2] as _).expect("valid memory range") }
558 }
559 }
560
561 #[cfg(keyos)]
562 impl AsScalar<2> for MemoryRange {
563 fn as_scalar(&self) -> [u32; 2] { [self.as_ptr() as _, self.len() as _] }
564 }
565
566 #[cfg(keyos)]
567 impl FromScalar<2> for MemoryRange {
568 fn from_scalar(value: [u32; 2]) -> Self {
569 unsafe { MemoryRange::new(value[0] as _, value[1] as _).expect("valid memory range") }
570 }
571 }
572
573 impl<T: FromScalar<3>> FromScalar<4> for Option<T> {
576 fn from_scalar(value: [u32; 4]) -> Self {
577 if value[0] == 1 {
578 Some(T::from_scalar([value[1], value[2], value[3]]))
579 } else {
580 None
581 }
582 }
583 }
584
585 impl<T: AsScalar<3>> AsScalar<4> for Option<T> {
586 fn as_scalar(&self) -> [u32; 4] {
587 match self {
588 Some(value) => {
589 let s = value.as_scalar();
590 [1, s[0], s[1], s[2]]
591 }
592 None => [0, 0, 0, 0],
593 }
594 }
595 }
596
597 impl<T: FromScalar<3>, E: FromScalar<3>> FromScalar<4> for Result<T, E> {
598 fn from_scalar(value: [u32; 4]) -> Self {
599 if value[0] == 1 {
600 Ok(T::from_scalar([value[1], value[2], value[3]]))
601 } else {
602 Err(E::from_scalar([value[1], value[2], value[3]]))
603 }
604 }
605 }
606
607 impl<T: AsScalar<3>, E: AsScalar<3>> AsScalar<4> for Result<T, E> {
608 fn as_scalar(&self) -> [u32; 4] {
609 match self {
610 Ok(value) => {
611 let s = value.as_scalar();
612 [1, s[0], s[1], s[2]]
613 }
614 Err(err) => {
615 let s = err.as_scalar();
616 [0, s[0], s[1], s[2]]
617 }
618 }
619 }
620 }
621}