Skip to main content

dope_net/wire/
mod.rs

1pub mod buffered;
2pub mod identity;
3pub mod reservation;
4pub mod send;
5
6use std::io;
7
8use crate::{Bytes, ProvidedLease, ProvidedView, RetainBytes};
9use dope_core::driver::DriverRef;
10use dope_core::driver::ready::ReadyKey;
11use dope_core::driver::token::Token;
12use o3::buffer::{Borrowed, Retained};
13
14use self::send::{Plain, Prepared, SendStorage, Sent, Storage, Vectored};
15
16pub enum Reclaim {
17    OnSubmit,
18    OnComplete,
19}
20
21pub enum RecvChunk<'a, R> {
22    /// A transformed range that aliases the current provided receive buffer.
23    Borrowed(Bytes<Borrowed<'a>>),
24    /// Wire-owned output independent of the current provided receive buffer.
25    Owned(R),
26}
27
28/// A checked writer over uninitialized receive storage.
29///
30/// Its initialized length can only advance through methods that write every
31/// byte in the committed prefix.
32pub struct RecvTarget<'a> {
33    buffer: &'a mut Vec<u8>,
34    limit: usize,
35}
36
37impl<'a> RecvTarget<'a> {
38    pub fn new(buffer: &'a mut Vec<u8>) -> Self {
39        buffer.clear();
40        let limit = buffer.capacity();
41        Self { buffer, limit }
42    }
43
44    pub fn len(&self) -> usize {
45        self.buffer.len()
46    }
47
48    pub fn remaining(&self) -> usize {
49        self.limit - self.buffer.len()
50    }
51
52    pub fn write_prefix(&mut self, source: &[u8]) -> usize {
53        let amount = source.len().min(self.remaining());
54        self.buffer.extend_from_slice(&source[..amount]);
55        amount
56    }
57
58    #[doc(hidden)]
59    pub fn with_limit(&mut self, limit: usize, fill: impl FnOnce(&mut RecvTarget<'_>)) -> usize {
60        let initial = self.buffer.len();
61        let previous = self.limit;
62        self.limit = initial + limit.min(self.remaining());
63        fill(self);
64        self.limit = previous;
65        self.buffer.len() - initial
66    }
67}
68
69/// An owned receive result that can be drained without allocation or
70/// knowledge of its wire-specific representation.
71pub trait RecvCursor: Unpin {
72    fn remaining(&self) -> usize;
73
74    /// Copies and consumes a logical prefix into checked uninitialized storage.
75    fn read_into(&mut self, target: &mut RecvTarget<'_>);
76
77    fn is_empty(&self) -> bool {
78        self.remaining() == 0
79    }
80}
81
82impl RecvCursor for Bytes<Retained> {
83    fn remaining(&self) -> usize {
84        self.len()
85    }
86
87    fn read_into(&mut self, target: &mut RecvTarget<'_>) {
88        let count = target.write_prefix(self.as_slice());
89        self.consume_prefix_up_to(count);
90    }
91}
92
93impl RecvCursor for ProvidedView<'_> {
94    fn remaining(&self) -> usize {
95        self.len()
96    }
97
98    fn read_into(&mut self, target: &mut RecvTarget<'_>) {
99        let count = target.write_prefix(self.as_slice());
100        self.advance(count);
101    }
102}
103
104/// A connection-local receive capability offered to a retained cursor.
105///
106/// A wire claims this capability only when the cursor owns a resource that
107/// must be released before the same connection may receive again.
108#[must_use]
109pub struct RecvCredit<'d> {
110    driver: DriverRef<'d>,
111    ready: ReadyKey<'d>,
112    target: Token,
113}
114
115/// A claimed receive capability. Dropping it schedules the exact connection
116/// that supplied the capability, allowing its deferred receive stream to
117/// resume.
118#[must_use]
119pub struct RecvCreditGuard<'d>(RecvCredit<'d>);
120
121impl<'d> RecvCredit<'d> {
122    pub(crate) fn new(driver: DriverRef<'d>, ready: ReadyKey<'d>, target: Token) -> Self {
123        Self {
124            driver,
125            ready,
126            target,
127        }
128    }
129
130    pub fn claim(self) -> Result<RecvCreditGuard<'d>, Self> {
131        if !self.driver.arm_recv_credit(self.ready, self.target) {
132            return Err(self);
133        }
134        Ok(RecvCreditGuard(self))
135    }
136}
137
138impl Drop for RecvCreditGuard<'_> {
139    fn drop(&mut self) {
140        self.0
141            .driver
142            .release_recv_credit(self.0.ready, self.0.target);
143    }
144}
145
146#[derive(Clone, Copy)]
147pub struct RuntimeLimits {
148    max_connections: usize,
149    max_retained_recv_chunks: usize,
150    max_recv_len: usize,
151    recv_credit: bool,
152}
153
154impl RuntimeLimits {
155    pub fn new(
156        max_connections: usize,
157        max_retained_recv_chunks: usize,
158        max_recv_len: usize,
159    ) -> Self {
160        Self {
161            max_connections,
162            max_retained_recv_chunks,
163            max_recv_len,
164            recv_credit: false,
165        }
166    }
167
168    #[doc(hidden)]
169    pub fn with_recv_credit(mut self) -> Self {
170        self.recv_credit = true;
171        self
172    }
173
174    pub fn max_connections(self) -> usize {
175        self.max_connections
176    }
177
178    pub fn max_retained_recv_chunks(self) -> usize {
179        self.max_retained_recv_chunks
180    }
181
182    pub fn max_recv_len(self) -> usize {
183        self.max_recv_len
184    }
185
186    pub fn recv_credit(self) -> bool {
187        self.recv_credit
188    }
189}
190
191pub trait Wire: 'static + Sized {
192    /// Connection-local state, scoped to the driver domain that owns it.
193    type Connection<'d>: 'd
194    where
195        Self: 'd;
196    /// Stable storage from which connection-local state may borrow.
197    type ConnectionStorage: 'static;
198    type InitConfig<'d>: 'd
199    where
200        Self: 'd;
201    type RuntimeContext<'d>: 'd
202    where
203        Self: 'd;
204    type Open<'a, 'd>: OpenReservation<Self::Connection<'d>, Self::SendStorage>
205    where
206        'd: 'a;
207    type Recv<'a>: RetainBytes + 'a;
208    type RecvBatch<'a>: ExactSizeIterator<Item = RecvChunk<'a, Self::Recv<'a>>>
209    where
210        Self: 'a;
211    type RetainedRecv<'d>: RecvCursor + 'd
212    where
213        Self: 'd;
214    type SendStorage: SendStorage;
215
216    const RECLAIM: Reclaim;
217
218    const RAW_RECV: bool = false;
219
220    /// Whether this wire can retain a connection-local receive credit.
221    const RECV_CREDIT: bool = false;
222
223    fn connection_storage(capacity: usize) -> io::Result<Self::ConnectionStorage>;
224
225    fn runtime_context<'d>(
226        limits: RuntimeLimits,
227        config: Self::InitConfig<'d>,
228    ) -> io::Result<Self::RuntimeContext<'d>>
229    where
230        Self: 'd;
231
232    fn prepare_open<'a, 'd>(
233        runtime: &'a mut Self::RuntimeContext<'d>,
234    ) -> Option<Self::Open<'a, 'd>>
235    where
236        'd: 'a;
237
238    fn holds_plain<'d>(_wire: &Self::Connection<'d>, _send: &Self::SendStorage) -> bool {
239        false
240    }
241
242    /// Transforms one unique initialized provided-buffer completion. The wire
243    /// may mutate `bytes` in place before returning borrowed ranges.
244    fn process_recv<'a, 'd>(
245        wire: &mut Self::Connection<'d>,
246        runtime: &mut Self::RuntimeContext<'d>,
247        bytes: &'a mut [u8],
248    ) -> Self::RecvBatch<'a>;
249
250    /// Transforms a receive completion whose result may outlive this call.
251    /// Ownership of the provided buffer is explicit, so a wire may retain it
252    /// directly or return an independent owned representation.
253    fn process_retained_recv<'a, 'd>(
254        wire: &mut Self::Connection<'d>,
255        runtime: &mut Self::RuntimeContext<'d>,
256        bytes: ProvidedLease<'a>,
257    ) -> Option<Self::RetainedRecv<'a>>;
258
259    /// Claims a connection-local receive credit for a retained cursor.
260    ///
261    /// The default leaves receive flow unchanged. A wire returns `Ok(())` only
262    /// after `credit.claim()` succeeds and stores the resulting guard in
263    /// `recv`. It releases that guard as soon as the resource imposing
264    /// backpressure is released.
265    fn bind_recv_credit<'d>(
266        recv: &mut Self::RetainedRecv<'d>,
267        credit: RecvCredit<'d>,
268    ) -> Result<(), RecvCredit<'d>> {
269        let _ = recv;
270        Err(credit)
271    }
272
273    fn recv_eof<'d>(_wire: &mut Self::Connection<'d>) {}
274
275    fn prepare_send<'a, 'd>(
276        wire: &'a mut Self::Connection<'d>,
277        send: Storage<'a, Self::SendStorage>,
278        plain: Plain<'a>,
279    ) -> Prepared<'a>;
280
281    fn prepare_send_vectored<'a, 'd>(
282        wire: &'a mut Self::Connection<'d>,
283        send: Storage<'a, Self::SendStorage>,
284        plain: Vectored<'a>,
285    ) -> Prepared<'a>;
286
287    fn submit_failed<'d>(_wire: &mut Self::Connection<'d>) {}
288
289    fn after_send<'a, 'd>(
290        wire: &'a mut Self::Connection<'d>,
291        send: Storage<'a, Self::SendStorage>,
292        sent: Sent,
293    ) -> Prepared<'a>;
294
295    fn flush_pending<'a, 'd>(
296        wire: &'a mut Self::Connection<'d>,
297        send: Storage<'a, Self::SendStorage>,
298    ) -> Prepared<'a>;
299
300    fn graceful_close<'a, 'd>(
301        _wire: &'a mut Self::Connection<'d>,
302        send: Storage<'a, Self::SendStorage>,
303    ) -> Prepared<'a> {
304        send.empty(0)
305    }
306}
307
308pub trait OpenReservation<W, S> {
309    fn commit(self) -> (W, S);
310}
311
312pub trait OpenRollback<W, S> {
313    fn rollback_open(&mut self, open: (W, S));
314}
315
316pub struct ReadyOpen<W, S> {
317    committed: (W, S),
318}
319
320impl<W, S> ReadyOpen<W, S> {
321    pub fn new(wire: W, send: S) -> Self {
322        Self {
323            committed: (wire, send),
324        }
325    }
326}
327
328impl<W, S> OpenReservation<W, S> for ReadyOpen<W, S> {
329    fn commit(self) -> (W, S) {
330        self.committed
331    }
332}