1use std::any::type_name;
7
8use rkyv::rancor::{self, Source as _};
9use whence::WhenceExt;
10
11use crate::{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(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 = 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 init: AsyncMessageInit<[u32; 4]> = crate::Buffer::deserialize(mem).whence()?;
232 let AsyncMessageInit { cid, msg_id, msg } = init;
233 let request = BlockingScalarResponse {
234 responder: Some(Responder::Async { cid, msg_id }),
235 pid,
236 default: S::default_response,
237 response: None,
238 };
239 let request = BlockingScalarRequest { message: M::from_scalar(msg), response: request };
240 handler.handle(request, context);
241 Ok(())
242 }
243 _ => Err(rancor::Error::new(WrongMessageTypeError)).whence(),
244 }
245}
246
247pub fn decode_scalar_async_response<R>(raw: xous::MessageEnvelope) -> R
249where
250 R: ScalarCodec,
251{
252 try_decode_scalar_async_response(raw).unwrap()
253}
254
255pub fn try_decode_scalar_async_response<R>(mut raw: xous::MessageEnvelope) -> whence::Result<R, crate::Error>
257where
258 R: ScalarCodec,
259{
260 let scalar = extract_scalar_message(&mut raw).whence()?;
261 Ok(R::from_scalar(scalar))
262}
263
264pub trait Scalar: ScalarCodec + crate::MessageId {
268 fn to_message(&self) -> xous::ScalarMessage
269 where
270 Self: Sized,
271 {
272 scalar_to_message(self, Self::ID)
273 }
274}
275
276pub trait ScalarHandler<M>
278where
279 M: Scalar,
280 Self: Server,
281{
282 fn handle(&mut self, msg: M, sender: xous::PID, context: &mut ServerContext<Self>);
284}
285
286pub fn send_scalar<M>(cid: xous::CID, msg: M)
290where
291 M: Scalar,
292{
293 try_send_scalar(cid, msg).unwrap()
294}
295
296pub fn try_send_scalar<M>(cid: xous::CID, msg: M) -> whence::Result<(), xous::Error>
300where
301 M: Scalar,
302{
303 let msg = xous::Message::Scalar(msg.to_message());
304 xous::send_message(cid, msg).whence()?;
305 Ok(())
306}
307
308pub fn send_scalar_nowait<M>(cid: xous::CID, msg: M) -> whence::Result<(), xous::Error>
311where
312 M: Scalar,
313{
314 let msg = xous::Message::Scalar(msg.to_message());
315 xous::try_send_message(cid, msg).whence()?;
316 Ok(())
317}
318
319pub fn handle_scalar_message<M, S>(
321 handler: &mut S,
322 mut raw: xous::MessageEnvelope,
323 context: &mut ServerContext<S>,
324) where
325 M: Scalar,
326 S: ScalarHandler<M>,
327{
328 let pid = raw.sender.pid().unwrap();
329
330 match &mut raw.body {
331 xous::Message::Scalar(scalar) => {
332 let message = scalar_from_message(scalar);
333 handler.handle(message, pid, context);
334 }
335 _ => {
336 log::error!("invalid Scalar message {} (ID {}) from PID {pid}: {raw:?}", type_name::<M>(), M::ID,);
337 }
338 }
339}
340
341pub(crate) fn scalar_async_response_handler<M, S>(
345 handler: &mut S,
346 raw: xous::MessageEnvelope,
347 context: &mut ServerContext<S>,
348) where
349 M: BlockingScalar,
350 S: BlockingScalarResponseHandler<M::Response>,
351{
352 let msg_id = raw.id();
353 let sender = raw.sender.pid().unwrap();
354
355 match try_decode_scalar_async_response(raw) {
356 Ok(response) => {
357 handler.handle_response(response, sender, context);
358 }
359 Err(e) => log::warn!("invalid async scalar response {e}"),
360 }
361
362 context.remove_handler(msg_id);
363}
364
365#[derive(Debug)]
366enum Responder {
367 Sync(xous::MessageEnvelope),
369 Async { cid: xous::CID, msg_id: xous::MessageId },
371}
372
373impl Responder {
374 fn respond<R>(self, response: R) -> whence::Result<(), xous::Error>
375 where
376 R: ScalarCodec,
377 {
378 match self {
379 Responder::Sync(envelope) => {
380 let [arg1, arg2, arg3, arg4] = response.as_scalar().map(|a| a as usize);
381 xous::return_scalar5(envelope.sender, arg1, arg2, arg3, arg4, 0).whence()
382 }
383 Responder::Async { cid, msg_id } => {
384 let _disconnect = defer::defer(|| {
385 xous::disconnect(cid).ok();
386 });
387 let msg = scalar_to_message(&response, msg_id);
388 xous::try_send_message(cid, xous::Message::Scalar(msg)).whence()?;
389 Ok(())
390 }
391 }
392 }
393}
394
395pub use codec::*;
398
399mod codec {
400 use xous::MemoryRange;
401
402 pub trait FromScalar<const N: usize> {
405 fn from_scalar(value: [u32; N]) -> Self;
406 }
407
408 pub trait AsScalar<const N: usize> {
409 fn as_scalar(&self) -> [u32; N];
410 }
411
412 impl<T: FromScalar<3>> FromScalar<4> for T {
415 fn from_scalar(value: [u32; 4]) -> Self { Self::from_scalar([value[0], value[1], value[2]]) }
416 }
417
418 impl<T: AsScalar<3>> AsScalar<4> for T {
419 fn as_scalar(&self) -> [u32; 4] {
420 let s = Self::as_scalar(self);
421 [s[0], s[1], s[2], 0]
422 }
423 }
424
425 impl<T: FromScalar<2>> FromScalar<3> for T {
426 fn from_scalar(value: [u32; 3]) -> Self { Self::from_scalar([value[0], value[1]]) }
427 }
428
429 impl<T: AsScalar<2>> AsScalar<3> for T {
430 fn as_scalar(&self) -> [u32; 3] {
431 let s = Self::as_scalar(self);
432 [s[0], s[1], 0]
433 }
434 }
435
436 impl<T: FromScalar<1>> FromScalar<2> for T {
437 fn from_scalar(value: [u32; 2]) -> Self { Self::from_scalar([value[0]]) }
438 }
439
440 impl<T: AsScalar<1>> AsScalar<2> for T {
441 fn as_scalar(&self) -> [u32; 2] {
442 let s = Self::as_scalar(self);
443 [s[0], 0]
444 }
445 }
446
447 impl FromScalar<1> for () {
450 fn from_scalar(_value: [u32; 1]) -> Self {}
451 }
452
453 impl AsScalar<1> for () {
454 fn as_scalar(&self) -> [u32; 1] { [0] }
455 }
456
457 impl FromScalar<1> for usize {
458 fn from_scalar(value: [u32; 1]) -> Self { value[0] as usize }
459 }
460
461 impl AsScalar<1> for usize {
462 fn as_scalar(&self) -> [u32; 1] { [*self as u32] }
463 }
464
465 impl FromScalar<1> for i32 {
466 fn from_scalar(value: [u32; 1]) -> Self { value[0] as i32 }
467 }
468
469 impl AsScalar<1> for i32 {
470 fn as_scalar(&self) -> [u32; 1] { [*self as u32] }
471 }
472
473 impl FromScalar<1> for u8 {
474 fn from_scalar(value: [u32; 1]) -> Self { value[0] as u8 }
475 }
476
477 impl AsScalar<1> for u8 {
478 fn as_scalar(&self) -> [u32; 1] { [*self as u32] }
479 }
480
481 impl FromScalar<1> for u16 {
482 fn from_scalar(value: [u32; 1]) -> Self { value[0] as u16 }
483 }
484
485 impl AsScalar<1> for u16 {
486 fn as_scalar(&self) -> [u32; 1] { [*self as u32] }
487 }
488
489 impl FromScalar<1> for u32 {
490 fn from_scalar(value: [u32; 1]) -> Self { value[0] }
491 }
492
493 impl AsScalar<1> for u32 {
494 fn as_scalar(&self) -> [u32; 1] { [*self] }
495 }
496
497 impl FromScalar<2> for u64 {
498 fn from_scalar(value: [u32; 2]) -> Self { (value[0] as u64) | ((value[1] as u64) << 32) }
499 }
500
501 impl AsScalar<2> for u64 {
502 fn as_scalar(&self) -> [u32; 2] { [*self as u32, (*self >> 32) as u32] }
503 }
504
505 impl FromScalar<1> for bool {
506 fn from_scalar(value: [u32; 1]) -> Self { value[0] != 0 }
507 }
508
509 impl AsScalar<1> for bool {
510 fn as_scalar(&self) -> [u32; 1] { [if *self { 1 } else { 0 }] }
511 }
512
513 impl FromScalar<1> for xous::PID {
516 fn from_scalar(value: [u32; 1]) -> Self { xous::PID::new(value[0].try_into().unwrap()).unwrap() }
517 }
518
519 impl AsScalar<1> for xous::PID {
520 fn as_scalar(&self) -> [u32; 1] { [self.get() as u32] }
521 }
522
523 impl AsScalar<4> for xous::SID {
524 fn as_scalar(&self) -> [u32; 4] {
525 let s = self.to_u32();
526 [s.0, s.1, s.2, s.3]
527 }
528 }
529
530 impl FromScalar<4> for xous::SID {
531 fn from_scalar(value: [u32; 4]) -> Self { Self::from_u32(value[0], value[1], value[2], value[3]) }
532 }
533
534 impl FromScalar<4> for xous::AppId {
535 fn from_scalar(value: [u32; 4]) -> Self { value.into() }
536 }
537
538 impl AsScalar<4> for xous::AppId {
539 fn as_scalar(&self) -> [u32; 4] { self.into() }
540 }
541
542 #[cfg(not(keyos))]
545 impl AsScalar<3> for MemoryRange {
546 fn as_scalar(&self) -> [u32; 3] {
547 let ptr = self.as_ptr() as usize;
548 [ptr as _, (ptr >> 32) as _, self.len() as _]
549 }
550 }
551
552 #[cfg(not(keyos))]
553 impl FromScalar<3> for MemoryRange {
554 fn from_scalar(value: [u32; 3]) -> Self {
555 let ptr = (value[0] as usize) | ((value[1] as usize) << 32);
556 unsafe { MemoryRange::new(ptr, value[2] as _).expect("valid memory range") }
557 }
558 }
559
560 #[cfg(keyos)]
561 impl AsScalar<2> for MemoryRange {
562 fn as_scalar(&self) -> [u32; 2] { [self.as_ptr() as _, self.len() as _] }
563 }
564
565 #[cfg(keyos)]
566 impl FromScalar<2> for MemoryRange {
567 fn from_scalar(value: [u32; 2]) -> Self {
568 unsafe { MemoryRange::new(value[0] as _, value[1] as _).expect("valid memory range") }
569 }
570 }
571
572 impl<T: FromScalar<3>> FromScalar<4> for Option<T> {
575 fn from_scalar(value: [u32; 4]) -> Self {
576 if value[0] == 1 {
577 Some(T::from_scalar([value[1], value[2], value[3]]))
578 } else {
579 None
580 }
581 }
582 }
583
584 impl<T: AsScalar<3>> AsScalar<4> for Option<T> {
585 fn as_scalar(&self) -> [u32; 4] {
586 match self {
587 Some(value) => {
588 let s = value.as_scalar();
589 [1, s[0], s[1], s[2]]
590 }
591 None => [0, 0, 0, 0],
592 }
593 }
594 }
595
596 impl<T: FromScalar<3>, E: FromScalar<3>> FromScalar<4> for Result<T, E> {
597 fn from_scalar(value: [u32; 4]) -> Self {
598 if value[0] == 1 {
599 Ok(T::from_scalar([value[1], value[2], value[3]]))
600 } else {
601 Err(E::from_scalar([value[1], value[2], value[3]]))
602 }
603 }
604 }
605
606 impl<T: AsScalar<3>, E: AsScalar<3>> AsScalar<4> for Result<T, E> {
607 fn as_scalar(&self) -> [u32; 4] {
608 match self {
609 Ok(value) => {
610 let s = value.as_scalar();
611 [1, s[0], s[1], s[2]]
612 }
613 Err(err) => {
614 let s = err.as_scalar();
615 [0, s[0], s[1], s[2]]
616 }
617 }
618 }
619 }
620}
621
622#[inline]
623pub(crate) fn extract_scalar_message(
624 raw: &mut xous::MessageEnvelope,
625) -> core::result::Result<[u32; 4], rkyv::rancor::Error> {
626 match &mut raw.body {
627 xous::Message::Scalar(scalar) => {
628 let [_, arg1, arg2, arg3, arg4] = scalar.to_usize().map(|a| a as u32);
629 Ok([arg1, arg2, arg3, arg4])
630 }
631 _ => rkyv::rancor::fail!(crate::WrongMessageTypeError),
632 }
633}
634
635#[inline]
636pub(crate) fn scalar_to_message(s: &impl crate::AsScalar<4>, msg_id: usize) -> xous::ScalarMessage {
637 let [arg1, arg2, arg3, arg4] = s.as_scalar().map(|a| a as usize);
638 xous::ScalarMessage { id: msg_id, arg1, arg2, arg3, arg4 }
639}
640
641#[inline]
642pub(crate) fn scalar_from_message<M: crate::FromScalar<4>>(msg: &xous::ScalarMessage) -> M {
643 let [_, arg1, arg2, arg3, arg4] = msg.to_usize().map(|a| a as u32);
644 M::from_scalar([arg1, arg2, arg3, arg4])
645}