1use dope_sys::{
2 io::{reactor::complete, socket::addr},
3 kernel, memory, probe,
4 probe::{accept, receive, session},
5 ring::{create, inspect, map, prepare::Rejection},
6};
7
8use crate::{
9 Engine,
10 driver::{
11 life::native::{
12 create::{Kernel, Mapping},
13 host::{Receive, Selection},
14 },
15 result,
16 result::{IoOperation, poll::fault},
17 settings, storage,
18 },
19 io::{socket, transfer},
20};
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23#[repr(transparent)]
24pub(crate) struct Failure(pub(crate) storage::Failure);
25
26impl From<Failure> for storage::Failure {
27 fn from(failure: Failure) -> Self {
28 failure.0
29 }
30}
31
32impl<E> From<probe::Syscall<result::Probe, E>> for Failure
33where
34 Kernel: From<E>,
35{
36 fn from(cause: probe::Syscall<result::Probe, E>) -> Self {
37 Self(storage::Failure::Kernel {
38 operation: IoOperation::Probe(cause.probe),
39 cause: Kernel::from(cause.error).0,
40 })
41 }
42}
43
44impl From<probe::Syscall<result::Probe, probe::Creation>> for Failure {
45 fn from(cause: probe::Syscall<result::Probe, probe::Creation>) -> Self {
46 match cause.error {
47 probe::Creation::Syscall(error)
48 | probe::Creation::Local(addr::Local::Syscall(error)) => probe::Syscall {
49 probe: cause.probe,
50 error,
51 }
52 .into(),
53 probe::Creation::Local(addr::Local::Length { actual, capacity }) => {
54 Self(storage::Failure::Probe(result::ProbeError::new(
55 cause.probe,
56 result::Violation::InvalidAddress(socket::Error::Storage { actual, capacity }),
57 )))
58 }
59 }
60 }
61}
62
63impl From<accept::Check<result::Probe>> for Failure {
64 fn from(check: accept::Check<result::Probe>) -> Self {
65 let (probe, cause) = match check {
66 accept::Check::Early(probe) => (probe, result::Violation::EarlyTermination),
67 accept::Check::Outside { probe, cause } => {
68 (probe, result::Violation::EscapedSlot(cause.into()))
69 }
70 };
71 Self(storage::Failure::Probe(result::ProbeError::new(
72 probe, cause,
73 )))
74 }
75}
76
77impl From<memory::Error> for Failure {
78 fn from(error: memory::Error) -> Self {
79 Self(storage::Failure::Mapping(Mapping::from(error).0))
80 }
81}
82
83impl<R, U> From<session::Primary<R, U>> for Failure
84where
85 Kernel: From<R> + From<U>,
86{
87 fn from(primary: session::Primary<R, U>) -> Self {
88 let (op, cause) = match primary {
89 session::Primary::Register(error) => {
90 (IoOperation::RegisterCanaryBuffers, Kernel::from(error).0)
91 }
92 session::Primary::Unregister(error) => {
93 (IoOperation::UnregisterCanaryBuffers, Kernel::from(error).0)
94 }
95 };
96 Self(storage::Failure::Kernel {
97 operation: op,
98 cause,
99 })
100 }
101}
102
103impl<E> From<receive::Install<E>> for Failure
104where
105 Kernel: From<E>,
106{
107 fn from(failure: receive::Install<E>) -> Self {
108 let op = match failure.mode {
109 receive::Mode::Data => IoOperation::InstallReceiveFile,
110 receive::Mode::Message => IoOperation::InstallReceiveMessageFile,
111 };
112 Self(storage::Failure::Kernel {
113 operation: op,
114 cause: Kernel::from(failure.error).0,
115 })
116 }
117}
118
119impl<O, E, I, L, C> From<session::Checked<result::Probe, O, E, I, L, C, result::ProbeError>>
120 for Failure
121where
122 Engine: complete::Observe<Observation = O>,
123 Kernel: From<E>,
124 Selection: From<(I, settings::Buffers)>,
125 transfer::Len: From<L>,
126 transfer::NonZero: From<C>,
127{
128 fn from(cause: session::Checked<result::Probe, O, E, I, L, C, result::ProbeError>) -> Self {
129 use dope_sys::memory::buffer::canary;
130 use session::Checked;
131
132 let (probe, fault) = match cause {
133 Checked::Wait(cause) => return cause.into(),
134 Checked::MissingBuffer(probe) => (probe, result::Violation::MissingBuffer),
135 Checked::Terminated(probe) => (probe, result::Violation::EarlyTermination),
136 Checked::Buffer { probe, failure } => {
137 let fault = match failure {
138 canary::Failure::Inspect(error) => {
139 return Self(storage::Failure::Probe(error));
140 }
141 canary::Failure::Index(index) => {
142 let layout = <Receive as memory::raw::Canary>::LAYOUT;
143 result::Violation::InvalidBuffer(
144 Selection::from((index, layout.0.buffers())).into_public(),
145 )
146 }
147 canary::Failure::Length { actual, capacity } => {
148 result::Violation::BufferLength {
149 actual: actual.into(),
150 capacity: capacity.into(),
151 }
152 }
153 };
154 (probe, fault)
155 }
156 };
157 Self(storage::Failure::Probe(result::ProbeError::new(
158 probe, fault,
159 )))
160 }
161}
162
163impl<C, E> From<inspect::Unsupported<C, E>> for Failure
164where
165 C: Into<<crate::Backend as kernel::Source>::Code>,
166 Kernel: From<E>,
167{
168 fn from(error: inspect::Unsupported<C, E>) -> Self {
169 Self(match error {
170 inspect::Unsupported::Opcode(code) => storage::Failure::Capability(
171 result::Capability::Opcode(result::Opcode::native(code)),
172 ),
173 inspect::Unsupported::Register(error) => storage::Failure::Kernel {
174 operation: IoOperation::RegisterOpcodes,
175 cause: Kernel::from(error).0,
176 },
177 })
178 }
179}
180
181impl From<(result::Probe, receive::Send)> for Failure {
182 fn from((probe, error): (result::Probe, receive::Send)) -> Self {
183 Self(match error {
184 receive::Send::Syscall(error) => storage::Failure::Kernel {
185 operation: IoOperation::Probe(probe),
186 cause: Kernel::from(error).0,
187 },
188 receive::Send::Partial(partial) => storage::Failure::Probe(result::ProbeError::new(
189 probe,
190 result::Violation::Send(fault::Send::from_partial(partial)),
191 )),
192 })
193 }
194}
195
196impl<C, F, R> From<Rejection<C, F, R>> for Failure
197where
198 Kernel: From<C> + From<F> + From<R>,
199{
200 fn from(cause: Rejection<C, F, R>) -> Self {
201 let (op, cause) = match cause {
202 Rejection::Feature(feature) => {
203 return Self(storage::Failure::Capability(result::Capability::Feature(
204 feature,
205 )));
206 }
207 Rejection::Cancel(cause) => (IoOperation::CancelRegistrations, Kernel::from(cause).0),
208 Rejection::Files(cause) => (IoOperation::RegisterFileTable, Kernel::from(cause).0),
209 Rejection::Range(cause) => (IoOperation::RegisterFileRange, Kernel::from(cause).0),
210 };
211 Self(storage::Failure::Kernel {
212 operation: op,
213 cause,
214 })
215 }
216}
217
218impl<S, M> From<create::Cause<S, M>> for Failure
219where
220 Kernel: From<S>,
221 Mapping: From<map::Map<M>>,
222{
223 fn from(cause: create::Cause<S, M>) -> Self {
224 Self(match cause {
225 create::Cause::Setup(cause) => storage::Failure::Kernel {
226 operation: IoOperation::ReactorCreate,
227 cause: Kernel::from(cause).0,
228 },
229 create::Cause::Layout(cause) => storage::Failure::RingLayout(cause),
230 create::Cause::Map(cause) => storage::Failure::Mapping(Mapping::from(cause).0),
231 })
232 }
233}
234
235impl<M, R, B> From<create::Primary<M, R, B>> for Failure
236where
237 Self: From<M>,
238 Kernel: From<R> + From<B>,
239{
240 fn from(primary: create::Primary<M, R, B>) -> Self {
241 Self(match primary {
242 create::Primary::Ring(error) => return Self::from(error),
243 create::Primary::Memory(error) => {
244 storage::Failure::Mapping(<Mapping as From<memory::Error>>::from(error).0)
245 }
246 create::Primary::Register(cause) => storage::Failure::Kernel {
247 operation: IoOperation::RegisterReactor,
248 cause: Kernel::from(cause).0,
249 },
250 create::Primary::Provided(cause) => storage::Failure::Kernel {
251 operation: IoOperation::RegisterProvidedBuffers,
252 cause: Kernel::from(cause).0,
253 },
254 })
255 }
256}
257
258impl<S, W> From<create::Failure<S, W>> for storage::Failure
259where
260 Mapping: From<S>,
261 Failure: From<W>,
262{
263 fn from(failure: create::Failure<S, W>) -> Self {
264 match failure {
265 create::Failure::Storage(error) => Self::Mapping(Mapping::from(error).0),
266 create::Failure::Memory(error) => {
267 Self::Mapping(<Mapping as From<memory::Error>>::from(error).0)
268 }
269 create::Failure::Wait(cause) => Failure::from(cause).0,
270 }
271 }
272}
273
274impl<O, E> From<probe::Cause<result::Probe, O, E>> for Failure
275where
276 Engine: complete::Observe<Observation = O>,
277 Kernel: From<E>,
278{
279 fn from(cause: probe::Cause<result::Probe, O, E>) -> Self {
280 use probe::Cause;
281
282 let (probe, fault) = match cause {
283 Cause::Enter { probe, error } => {
284 return Self(storage::Failure::Kernel {
285 operation: IoOperation::Probe(probe),
286 cause: Kernel::from(error).0,
287 });
288 }
289 Cause::Check(error) => {
290 return Self(storage::Failure::Probe(result::ProbeError::decode(error)));
291 }
292 Cause::Missing(probe) => (probe, result::Violation::MissingCompletion),
293 Cause::Unexpected { probe, observed } => (
294 probe,
295 result::Violation::UnexpectedCompletion {
296 expected: probe,
297 observed: fault::Observation::new(observed),
298 },
299 ),
300 Cause::Residual {
301 probe,
302 submit,
303 complete,
304 } => (
305 probe,
306 result::Violation::ResidualWork {
307 submissions: fault::Pending::from(submit),
308 completions: fault::Available::from(complete),
309 },
310 ),
311 };
312 Self(storage::Failure::Probe(result::ProbeError::new(
313 probe, fault,
314 )))
315 }
316}