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}