base_scheduler/socket_stream_reader.rs
1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use crate::{Cancellation, OperationResult, ReceiveBuffer};
5use std::{
6 future::Future,
7 io::{self, IoSliceMut},
8};
9
10/// One sequential input lane on a stream socket, bound to its creating scheduler. Independent reader and writer handles may operate concurrently. Backend registration and worker migration are internal details; moving a handle never changes its scheduler.
11///
12/// Owned chunks remain valid independently of the reader and can be retained for parsing or transferred to another task. Borrowed operations access payloads only synchronously within each poll, so dropping or forgetting a pending future cannot leave backend access to caller storage. Ordinary errors and cancellation end the current wait, without closing the reader or rolling back consumed bytes. No framing or read-ahead is required.
13///
14/// If an owned-operation future is abandoned while backend access continues, subsequent operations may report `WouldBlock` until it retires. Await `close` to establish retirement; separate handles provide independent lanes.
15pub trait SocketStreamReader: Send {
16 /// The owned chunk returned by [`read`](Self::read).
17 type Buffer: ReceiveBuffer;
18
19 /// Select whether ordinary reads must preserve progress across TCP urgent-data
20 /// boundaries. OOB support is disabled by default. The const parameter lets
21 /// backends specialize readiness handling without a runtime option check.
22 ///
23 /// With support disabled, backends may reject observed urgent data with
24 /// `Unsupported`; this is not a filter or a guarantee that every urgent byte
25 /// is detected. Socket aliases must not consume urgent data in this mode.
26 /// With support enabled, ordinary reads remain usable across urgent marks;
27 /// receiving the urgent byte itself remains a separate socket operation.
28 /// Backends that always use conservative reads need no specialization.
29 fn with_oob_support<const SUPPORT_OOB: bool>(
30 self,
31 ) -> impl SocketStreamReader<Buffer = Self::Buffer>
32 where
33 Self: Sized,
34 {
35 self
36 }
37
38 /// Read an owned initialized chunk. `None` means EOF or a closed reader. Holding every pool lease waits for capacity with cancellation. Idle readiness waits need not retain a payload buffer.
39 fn read(
40 &mut self,
41 cancellation: &Cancellation,
42 ) -> impl Future<Output = OperationResult<Option<Self::Buffer>>> + Send;
43
44 /// Read once into borrowed storage, returning a possibly short count. Zero with nonempty storage is EOF. An empty destination completes with zero after checking that the handle is open and cancellation has not been requested, without establishing EOF. Successful progress wins concurrent cancellation.
45 fn read_into(
46 &mut self,
47 buffer: &mut [u8],
48 cancellation: &Cancellation,
49 ) -> impl Future<Output = OperationResult<usize>> + Send;
50
51 /// Scatter a single read across borrowed ranges without allocating an I/O-vector array or copying payloads. Entirely empty storage follows `read_into`'s zero-capacity behavior.
52 fn read_vectored(
53 &mut self,
54 buffers: &mut [IoSliceMut<'_>],
55 cancellation: &Cancellation,
56 ) -> impl Future<Output = OperationResult<usize>> + Send;
57
58 /// Perform one borrowed transfer with explicit portable flags. Payload access ends before each poll returns; successful progress is returned in that poll.
59 fn read_into_with_flags(
60 &mut self,
61 buffer: &mut [u8],
62 flags: crate::SocketRecvFlags,
63 cancellation: &Cancellation,
64 ) -> impl Future<Output = OperationResult<usize>> + Send {
65 async move {
66 self.read_vectored_with_flags(
67 &mut [std::io::IoSliceMut::new(buffer)],
68 flags,
69 cancellation,
70 )
71 .await
72 .map(|result| result.bytes)
73 }
74 }
75
76 /// Perform one borrowed vectored transfer with explicit flags. Vectors are never advanced implicitly; a short result leaves their ranges unchanged.
77 fn read_vectored_with_flags(
78 &mut self,
79 buffers: &mut [std::io::IoSliceMut<'_>],
80 flags: crate::SocketRecvFlags,
81 cancellation: &Cancellation,
82 ) -> impl Future<Output = OperationResult<crate::SocketRecvResult>> + Send;
83
84 /// Perform one transfer while retaining a stable owner and return that original owner with every collected result. Backends may retain it independently until access retires after waiter abandonment.
85 fn read_owned<B: crate::IoBufMut>(
86 &mut self,
87 mut buffer: B,
88 cancellation: &Cancellation,
89 ) -> impl Future<Output = crate::BufferResult<B>> + Send {
90 async move {
91 let result = self.read_into(buffer.as_mut(), cancellation).await;
92 (result, buffer)
93 }
94 }
95
96 /// Transfer one message using an owned buffer sequence with explicit flags. Return the original sequence and its unchanged ranges on success, error, and cancellation. Kernel or worker access retains the full owner and stable I/O vectors through retirement, including after future abandonment.
97 fn read_owned_vectored<Buffers: crate::IoBufSequenceMut>(
98 &mut self,
99 buffers: Buffers,
100 flags: crate::SocketRecvFlags,
101 cancellation: &Cancellation,
102 ) -> impl Future<Output = (OperationResult<crate::SocketRecvResult>, Buffers)> + Send;
103
104 /// Stop input and await backend access and registration retirement. This does not close or shut down the socket. Cleanup remains available after cancellation; retry it if its future is dropped. Returned chunks remain valid. Drop the retired reader before exclusively closing its socket.
105 fn close(&mut self) -> impl Future<Output = io::Result<()>> + Send;
106}