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