1use core::{marker::PhantomData, task::Poll};
2
3use crate::{
4 api::{Reply, ReplyVariant, RequestVariant},
5 error::{Error, Result},
6 interrupt::InterruptFlag,
7};
8
9#[cfg(feature = "attestation-client")]
10pub mod attestation;
11#[cfg(feature = "certificate-client")]
12pub mod certificate;
13#[cfg(feature = "counter-client")]
14pub mod counter;
15#[cfg(feature = "crypto-client")]
16pub mod crypto;
17#[cfg(feature = "filesystem-client")]
18pub mod filesystem;
19#[cfg(feature = "management-client")]
20pub mod management;
21#[cfg(feature = "ui-client")]
22pub mod ui;
23
24#[derive(Copy, Clone, Debug)]
27#[non_exhaustive]
28pub enum ClientError {
29 Full,
30 Pending,
31 DataTooLarge,
32 SerializationFailed,
33}
34
35pub type ClientResult<'c, T, C> = Result<FutureResult<'c, T, C>, ClientError>;
36
37pub trait PollClient {
39 fn request<Rq: RequestVariant>(&mut self, req: Rq) -> ClientResult<'_, Rq::Reply, Self>;
40 fn poll(&mut self) -> Poll<Result<Reply, Error>>;
41 fn interrupt(&self) -> Option<&'static InterruptFlag> {
42 None
43 }
44}
45
46#[must_use = "Syscalls must be polled with the `syscall` macro"]
47pub struct FutureResult<'c, T, C: ?Sized>
48where
49 C: PollClient,
50{
51 pub(crate) client: &'c mut C,
52 __: PhantomData<T>,
53}
54
55impl<'c, T, C> FutureResult<'c, T, C>
56where
57 T: ReplyVariant,
58 C: PollClient,
59{
60 pub fn new(client: &'c mut C) -> Self {
61 Self {
62 client,
63 __: PhantomData,
64 }
65 }
66 pub fn poll(&mut self) -> Poll<Result<T, Error>> {
67 self.client
68 .poll()
69 .map(|result| result.and_then(TryFrom::try_from))
70 }
71}
72
73#[macro_export]
77macro_rules! block {
79 ($future_result:expr) => {{
80 let mut future_result = $future_result;
82 loop {
83 match future_result.poll() {
84 core::task::Poll::Ready(result) => {
85 break result;
86 }
87 core::task::Poll::Pending => {}
88 }
89 }
90 }};
91}
92
93#[macro_export]
94macro_rules! syscall {
95 ($pre_future_result:expr) => {{
96 let mut future_result = $pre_future_result.expect("no client error");
98 loop {
99 match future_result.poll() {
100 core::task::Poll::Ready(result) => {
101 break result.expect("no errors");
102 }
103 core::task::Poll::Pending => {}
104 }
105 }
106 }};
107}
108
109#[macro_export]
110macro_rules! try_syscall {
111 ($pre_future_result:expr) => {{
112 let mut future_result = $pre_future_result.expect("no client error");
114 loop {
115 match future_result.poll() {
116 core::task::Poll::Ready(result) => {
117 break result;
118 }
119 core::task::Poll::Pending => {}
120 }
121 }
122 }};
123}