1use std::{marker, mem};
2
3use dope_sys::{
4 engine,
5 io::socket::option::tuning::{Error, device},
6};
7use o3::depot::arena::slab::Vacancy;
8
9use crate::{
10 Engine, Errno, driver,
11 driver::{
12 result,
13 retained::{flight, flight::cancel},
14 route::{indices, kind},
15 },
16 io::{
17 event::net::{connect, tuning},
18 fd::handles,
19 socket::option,
20 },
21};
22
23#[doc(hidden)]
24pub struct Live;
25
26#[doc(hidden)]
27pub struct Cancelled;
28
29#[derive(Debug)]
31pub enum Cause {
32 Submit(result::SubmitError),
33 Option(Errno),
34}
35
36#[must_use = "a rejected establishment retains its exact descriptor and cause"]
37pub struct Rejection<'d> {
38 fd: handles::Descriptor<'d>,
39 cause: Cause,
40}
41
42#[must_use = "cancellation either transfers the item to the kernel or returns it for retry"]
43pub enum Cancellation<'d> {
44 Submitted(Tuning<'d, Cancelled>),
45 Retry {
46 item: Tuning<'d>,
47 error: result::SubmitError,
48 },
49}
50
51#[doc(hidden)]
52#[must_use = "a pending establishment owns its descriptor and completion authority"]
53#[repr(C)]
54pub struct Tuning<'d, State = Live> {
55 fd: handles::Descriptor<'d>,
56 flight: flight::Flight<'d, kind::Tuning>,
57 permit: <Engine as engine::Cancel<indices::SlotIndex>>::Permit,
58 state: marker::PhantomData<State>,
59}
60
61#[doc(hidden)]
62#[must_use = "a pending establishment owns its descriptor and completion authority"]
63#[repr(C)]
64pub struct Connection<'d, State = Live> {
65 fd: handles::Descriptor<'d>,
66 flight: flight::Flight<'d, kind::Connect>,
67 state: marker::PhantomData<State>,
68}
69
70#[must_use = "a completion mismatch retains both pending and completion authority"]
71pub struct Mismatch<T, C> {
72 item: T,
73 done: C,
74}
75
76impl<T, C> Mismatch<T, C> {
77 pub fn into_parts(self) -> (T, C) {
78 (self.item, self.done)
79 }
80}
81
82impl<'d, State> Tuning<'d, State> {
83 #[doc(hidden)]
84 pub const fn fd(&self) -> &handles::Descriptor<'d> {
85 &self.fd
86 }
87}
88
89impl<'d> Tuning<'d> {
90 pub(crate) fn from_native<P>(
91 finish: device::Finish<handles::Descriptor<'d>, flight::Reserved<'d, kind::Tuning>, P>,
92 ) -> option::Tuning<'d>
93 where
94 Engine: engine::Cancel<indices::SlotIndex, Permit = P>,
95 {
96 match finish {
97 device::Finish::Applied(fd) => option::Tuning::Applied(fd),
98 device::Finish::Pending(fd, target, permit) => option::Tuning::Pending(Self {
99 fd,
100 flight: target.commit(),
101 permit,
102 state: marker::PhantomData,
103 }),
104 }
105 }
106
107 fn commit<P>(self) -> Tuning<'d, Cancelled>
108 where
109 Engine: engine::Cancel<indices::SlotIndex, Permit = P>,
110 {
111 Tuning {
112 fd: self.fd,
113 flight: self.flight,
114 permit: self.permit,
115 state: marker::PhantomData,
116 }
117 }
118
119 pub fn cancel(self, driver: &mut driver::Context<'_, 'd>) -> Cancellation<'d> {
120 match engine::Cancel::cancel(driver.native().as_mut(), &self.permit, self.fd.index()) {
121 Ok(()) => Cancellation::Submitted(self.commit()),
122 Err(error) => Cancellation::Retry {
123 item: self,
124 error: result::SubmitError::queue(error),
125 },
126 }
127 }
128}
129
130impl<'d, State> Connection<'d, State> {
131 #[doc(hidden)]
132 pub const fn fd(&self) -> &handles::Descriptor<'d> {
133 &self.fd
134 }
135}
136
137impl<'d> Connection<'d> {
138 pub(crate) fn connect(
139 fd: handles::Descriptor<'d>,
140 flight: flight::Flight<'d, kind::Connect>,
141 ) -> Self {
142 Self {
143 fd,
144 flight,
145 state: marker::PhantomData,
146 }
147 }
148
149 pub fn try_cancel(
150 mut self,
151 driver: &mut driver::Context<'_, 'd>,
152 ) -> Result<Connection<'d, Cancelled>, (Self, cancel::Error)> {
153 match driver.native().try_stop_at(&mut self.flight, &self.fd) {
154 Ok(_) => Ok(self.commit()),
155 Err(error) => Err((self, error)),
156 }
157 }
158
159 pub(crate) fn commit(self) -> Connection<'d, Cancelled> {
160 Connection {
161 fd: self.fd,
162 flight: self.flight,
163 state: marker::PhantomData,
164 }
165 }
166}
167
168impl<'d> Rejection<'d> {
169 pub(crate) const fn new(fd: handles::Descriptor<'d>, cause: Cause) -> Self {
170 Self { fd, cause }
171 }
172
173 pub fn into_parts(self) -> (handles::Descriptor<'d>, Cause) {
174 (self.fd, self.cause)
175 }
176}
177
178impl<'d> From<Error<handles::Descriptor<'d>, Vacancy>> for Rejection<'d> {
179 fn from(error: Error<handles::Descriptor<'d>, Vacancy>) -> Self {
180 let (fd, cause) = match error {
181 Error::Full(fd, error) => (fd, Cause::Submit(result::SubmitError::queue(error))),
182 Error::Reserve(fd, error) => (fd, Cause::Submit(result::SubmitError::from(error))),
183 };
184 Self::new(fd, cause)
185 }
186}
187
188impl<'d, State> Tuning<'d, State> {
189 #[doc(hidden)]
190 pub fn complete(
191 self,
192 done: tuning::Completion<'d>,
193 ) -> Result<(handles::Descriptor<'d>, Result<(), Errno>), Mismatch<Self, tuning::Completion<'d>>>
194 {
195 let outcome = match done.resolve(self.flight.target()) {
196 Ok(outcome) => outcome,
197 Err(done) => return Err(Mismatch { item: self, done }),
198 };
199 drop(self.flight);
200 Ok((self.fd, outcome))
201 }
202}
203
204impl<'d, State> Connection<'d, State> {
205 #[doc(hidden)]
206 pub fn complete(
207 self,
208 done: connect::Completion<'d>,
209 ) -> Result<
210 (handles::Descriptor<'d>, Result<(), connect::Error>),
211 Mismatch<Self, connect::Completion<'d>>,
212 > {
213 let outcome = match done.resolve(self.flight.target()) {
214 Ok(outcome) => outcome,
215 Err(done) => return Err(Mismatch { item: self, done }),
216 };
217 drop(self.flight);
218 Ok((self.fd, outcome))
219 }
220}
221
222const _: () = {
223 assert!(mem::size_of::<Live>() == 0);
224 assert!(mem::size_of::<Cancelled>() == 0);
225 assert!(
226 mem::size_of::<Tuning<'_>>()
227 == mem::size_of::<(handles::Descriptor<'_>, flight::Flight<'_>)>()
228 );
229 assert!(
230 mem::align_of::<Tuning<'_>>()
231 == mem::align_of::<(handles::Descriptor<'_>, flight::Flight<'_>)>()
232 );
233 assert!(mem::offset_of!(Tuning<'_>, fd) == 0);
234 assert!(
235 mem::size_of::<Connection<'_>>()
236 == mem::size_of::<(handles::Descriptor<'_>, flight::Flight<'_, kind::Connect>)>()
237 );
238 assert!(mem::offset_of!(Connection<'_>, fd) == 0);
239 assert!(mem::size_of::<Rejection<'_>>() == mem::size_of::<(handles::Descriptor<'_>, Cause)>());
240 assert!(
241 mem::align_of::<Rejection<'_>>() == mem::align_of::<(handles::Descriptor<'_>, Cause)>()
242 );
243 assert!(mem::size_of::<Tuning<'_, Cancelled>>() == mem::size_of::<Tuning<'_>>());
244 assert!(mem::size_of::<Connection<'_, Cancelled>>() == mem::size_of::<Connection<'_>>());
245};
246
247impl<'d> From<device::Failure<handles::Descriptor<'d>, Vacancy>> for Rejection<'d> {
248 fn from(error: device::Failure<handles::Descriptor<'d>, Vacancy>) -> Self {
249 match error {
250 device::Failure::Option(fd, error) => Self::new(fd, Cause::Option(error)),
251 device::Failure::Reserve(error) => error.into(),
252 }
253 }
254}