Skip to main content

dope_core/driver/life/native/create/
failure.rs

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}