1use sidevm_env::{
3 messages::{AccountId, QueryRequest, SystemMessage},
4 InputChannel, OcallError,
5};
6
7use super::{ocall, ResourceId};
8use scale::{Decode, Error as CodecError};
9use std::{
10 future::Future,
11 pin::Pin,
12 task::{Context, Poll},
13};
14
15use lazy_static::lazy_static;
16
17pub struct Query {
19 pub origin: Option<AccountId>,
21 pub payload: Vec<u8>,
23 pub reply_tx: OneshotSender,
25}
26
27pub type GeneralMessage = Vec<u8>;
29
30pub struct OneshotSender {
32 res_id: ResourceId,
33}
34
35impl OneshotSender {
36 const fn new(res_id: ResourceId) -> Self {
37 Self { res_id }
38 }
39
40 pub fn send(self, data: &[u8]) -> Result<(), OcallError> {
42 ocall::oneshot_send(self.res_id.0, data)
43 }
44}
45
46pub struct Receiver<M> {
48 res_id: ResourceId,
49 _marker: std::marker::PhantomData<M>,
50}
51
52pub struct Next<'a, M> {
54 ch: &'a Receiver<M>,
55}
56
57impl<T> Receiver<T> {
58 pub const fn new(res_id: ResourceId) -> Self {
60 Self {
61 res_id,
62 _marker: std::marker::PhantomData,
63 }
64 }
65
66 pub fn next(&self) -> Next<T> {
68 Next { ch: self }
69 }
70}
71
72impl Future for Next<'_, GeneralMessage> {
73 type Output = Option<GeneralMessage>;
74
75 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
76 let waker_id = crate::env::tasks::intern_waker(cx.waker().clone());
77 match ocall::poll(waker_id, self.ch.res_id.0) {
78 Ok(msg) => Poll::Ready(Some(msg)),
79 Err(OcallError::EndOfFile) => Poll::Ready(None), Err(OcallError::Pending) => Poll::Pending,
81 Err(err) => panic!("unexpected error: {:?}", err),
82 }
83 }
84}
85
86impl Future for Next<'_, SystemMessage> {
87 type Output = Option<Result<SystemMessage, CodecError>>;
88
89 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
90 let waker_id = crate::env::tasks::intern_waker(cx.waker().clone());
91 match ocall::poll(waker_id, self.ch.res_id.0) {
92 Ok(msg) => Poll::Ready(Some(SystemMessage::decode(&mut &msg[..]))),
93 Err(OcallError::EndOfFile) => Poll::Ready(None), Err(OcallError::Pending) => Poll::Pending,
95 Err(err) => panic!("unexpected error: {:?}", err),
96 }
97 }
98}
99
100impl Future for Next<'_, Query> {
101 type Output = Option<Query>;
102
103 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
104 let waker_id = crate::env::tasks::intern_waker(cx.waker().clone());
105 match ocall::poll(waker_id, self.ch.res_id.0) {
106 Ok(msg) => {
107 let request =
108 QueryRequest::decode(&mut &msg[..]).expect("Failed to decode QueryRequest");
109 let reply_tx = OneshotSender::new(ResourceId(request.reply_tx));
110 Poll::Ready(Some(Query {
111 origin: request.origin,
112 payload: request.payload,
113 reply_tx,
114 }))
115 }
116 Err(OcallError::EndOfFile) => Poll::Ready(None), Err(OcallError::Pending) => Poll::Pending,
118 Err(err) => panic!("unexpected error: {:?}", err),
119 }
120 }
121}
122
123macro_rules! singleton_channel {
124 ($ch: ident) => {{
125 lazy_static! {
126 static ref RX: Receiver<$ch> = {
127 let res_id = ocall::create_input_channel(InputChannel::$ch)
128 .expect("Failed to create input channel");
129 Receiver::new(ResourceId(res_id))
130 };
131 }
132 &*RX
133 }};
134}
135
136pub fn input_messages() -> &'static Receiver<GeneralMessage> {
141 singleton_channel!(GeneralMessage)
142}
143
144pub fn incoming_system_messages() -> &'static Receiver<SystemMessage> {
147 singleton_channel!(SystemMessage)
148}
149
150pub fn incoming_queries() -> &'static Receiver<Query> {
152 singleton_channel!(Query)
153}