1extern crate alloc;
27
28use portal::ipc::{IpcError, IpcResult};
29use vera_portal::{
30 ConnectHandleError, HandleUpdateKind, RecvHandleError, SendHandleError, ServeHandleError,
31 WaitSignal,
32 sys_client::{close, connect, recv, send, serve, yield_now},
33};
34
35pub struct QuantumGlue(u64);
36
37impl QuantumGlue {
38 pub const fn new(handle: u64) -> Self {
39 Self(handle)
40 }
41
42 pub fn connect_to(service: &str) -> IpcResult<Self> {
44 let handle = loop {
45 match connect(service) {
46 Ok(okay) => {
47 break okay;
48 }
49 Err(ConnectHandleError::EndpointDoesNotExist) => {
50 yield_now();
51 }
52 }
53 };
54
55 Ok(Self::new(handle))
56 }
57}
58
59impl portal::ipc::IpcGlue for QuantumGlue {
60 fn disconnect(&mut self) {
61 close(self.0);
62 }
63}
64
65impl portal::ipc::Sender for QuantumGlue {
66 fn send(&mut self, bytes: &[u8]) -> IpcResult<()> {
67 send(self.0, bytes).map_err(|send_err| match send_err {
68 SendHandleError::InvalidHandle | SendHandleError::SendFailed => IpcError::GlueError,
69 SendHandleError::WouldBlock => IpcError::NotReady,
70 })?;
71
72 Ok(())
73 }
74}
75
76impl portal::ipc::Receiver for QuantumGlue {
77 fn recv(&mut self, bytes: &mut [u8]) -> IpcResult<usize> {
78 recv(self.0, bytes).map_err(|recv_err| match recv_err {
79 RecvHandleError::InvalidHandle | RecvHandleError::RecvFailed => IpcError::GlueError,
80 RecvHandleError::WouldBlock => IpcError::NotReady,
81 })
82 }
83}
84
85pub struct QuantumHost<T> {
87 server_handle: u64,
88 mapping: alloc::collections::BTreeMap<u64, T>,
89}
90
91impl<T> QuantumHost<T> {
92 pub fn host_on(service_name: &str) -> IpcResult<Self> {
93 match serve(service_name) {
94 Ok(server_handle) => Ok(Self {
95 server_handle,
96 mapping: alloc::collections::BTreeMap::new(),
97 }),
98 Err(ServeHandleError::AlreadyBound) => Err(IpcError::AlreadyUsed),
99 }
100 }
101
102 pub fn service_signal<N, R, W, D>(
103 &mut self,
104 signal: WaitSignal,
105 new_fn: N,
106 read_fn: R,
107 write_fn: W,
108 disconnect_fn: D,
109 ) -> IpcResult<()>
110 where
111 N: FnOnce(u64) -> IpcResult<T>,
112 R: FnOnce(&mut T) -> IpcResult<()>,
113 W: FnOnce(&mut T) -> IpcResult<()>,
114 D: FnOnce(T) -> IpcResult<()>,
115 {
116 match signal {
117 WaitSignal::HandleUpdate {
118 handle,
119 kind: HandleUpdateKind::NewConnection { new_handle },
120 } if handle == self.server_handle => {
121 self.mapping.insert(new_handle, new_fn(new_handle)?);
122 Ok(())
123 }
124 WaitSignal::HandleUpdate {
125 handle,
126 kind: HandleUpdateKind::Disconnected,
127 } => {
128 if let Some(prev) = self.mapping.remove(&handle) {
129 disconnect_fn(prev)?;
130 }
131
132 Ok(())
133 }
134 WaitSignal::HandleUpdate {
135 handle,
136 kind: HandleUpdateKind::ReadReady,
137 } => {
138 if let Some(mapping_inner) = self.mapping.get_mut(&handle) {
139 read_fn(mapping_inner)?;
140 }
141
142 Ok(())
143 }
144 WaitSignal::HandleUpdate {
145 handle,
146 kind: HandleUpdateKind::WriteReady,
147 } => {
148 if let Some(mapping_inner) = self.mapping.get_mut(&handle) {
149 write_fn(mapping_inner)?;
150 }
151
152 Ok(())
153 }
154 _ => Ok(()),
155 }
156 }
157}