xwt_core/
stream.rs

1//! Operations on the WebTransport streams.
2
3use core::future::Future;
4use core::num::NonZeroUsize;
5
6use crate::utils::{maybe, Error};
7
8/// The error code that can be passed when aborting the send or receive side
9/// of the stream.
10///
11/// Some WebTransport implementations allow not specifying the error codes
12/// explicitly - this is equivalent to passing the error code `0`.
13pub type ErrorCode = u32;
14
15/// Returns the error code for the stream operation error when the error
16/// originates from a stream abort.
17/// If an error
18///
19/// Useful to read the error from when the stream send side or receive side is
20/// aborted.
21///
22/// If no error code was passed, this call returns `0`.
23pub trait ErrorAsErrorCode: maybe::Send {
24    /// Returns the stream error code.
25    ///
26    /// If error is an internal implementation error as opposed to
27    /// a protocol error - returns `None`.
28    fn as_error_code(&self) -> Option<ErrorCode>;
29}
30
31/// Read the data from the stream.
32pub trait Read: maybe::Send {
33    /// An error that can occur while reading the stream.
34    type Error: Error + ErrorAsErrorCode + maybe::Send + maybe::Sync + 'static;
35
36    /// Read the data from the stream into a given buffer and return the amount
37    /// of bytes filled in the buffer or `None` if the stream is closed and does
38    /// not have any pending unread data.
39    ///
40    /// A would-be zero-length read should be reported as a error
41    /// with a zero error code.
42    /// There is a handy way to check that condition:
43    ///
44    /// ```ignore
45    /// let result = stream.read(buf).await;
46    /// let data = match result {
47    ///     Ok(read) => buf[..read.get()],
48    ///     Err(err) if err.is_closed() => {
49    ///         // Stream ended.
50    ///         return;
51    ///     }
52    ///     Err(err) => {
53    ///         panic!("something went wrong");
54    ///     }
55    /// };
56    /// ```
57    fn read(
58        &mut self,
59        buf: &mut [u8],
60    ) -> impl Future<Output = Result<NonZeroUsize, Self::Error>> + maybe::Send;
61}
62
63/// Write the data to a stream.
64pub trait Write: maybe::Send {
65    /// An error that can occur while writing to the stream.
66    type Error: Error + ErrorAsErrorCode + maybe::Send + maybe::Sync + 'static;
67
68    /// Write the data from the given buffer into the stream, returning
69    /// the amount of of bytes that were successfully written into the stream.
70    /// If the returned amount is smaller than the size of the data that was
71    /// being written, the user should try writing the remaining data again.
72    fn write(
73        &mut self,
74        buf: &[u8],
75    ) -> impl Future<Output = Result<NonZeroUsize, Self::Error>> + maybe::Send;
76}
77
78/// Abort the read stream.
79///
80/// Sends a signal to the peer that the read side of the stream has been
81/// aborted.
82/// Discards the receive buffer; the peer is typically expected to abort
83/// the corresponding send side in response.
84///
85/// An unsigned 8-bit error code can be supplied as a part of the signal
86/// to the peer; if omitted, the error code is presumed to be `0`.
87pub trait ReadAbort: maybe::Send {
88    /// An error that can occur while stopping the stream.
89    type Error: Error + maybe::Send + maybe::Sync + 'static;
90
91    /// Abort the stream.
92    fn abort(
93        self,
94        error_code: ErrorCode,
95    ) -> impl Future<Output = Result<(), Self::Error>> + maybe::Send;
96}
97
98/// Abort the write stream.
99///
100/// Sends a signal to the peer that the write side of the stream has been
101/// aborted.
102/// Discards the send buffer; if possible, no currently outstanding data
103/// is transmitted or retransmitted.
104///
105/// An unsigned 8-bit error code can be supplied as a part of the signal to
106/// the peer; if omitted, the error code is presumed to be `0`.
107pub trait WriteAbort: maybe::Send {
108    /// An error that can occur while stopping the stream.
109    type Error: Error + maybe::Send + maybe::Sync + 'static;
110
111    /// Abort the stream.
112    fn abort(
113        self,
114        error_code: ErrorCode,
115    ) -> impl Future<Output = Result<(), Self::Error>> + maybe::Send;
116}
117
118/// Wait for the write stream to abort.
119///
120/// This can happen when the "read" part aborts the stream.
121pub trait WriteAborted: maybe::Send {
122    /// An error that can occur while waiting for a stream to be aborted.
123    type Error: Error + maybe::Send + maybe::Sync + 'static;
124
125    /// Wait for a stream's corresponding read side to abort.
126    fn aborted(self) -> impl Future<Output = Result<ErrorCode, Self::Error>> + maybe::Send;
127}
128
129/// Wait for the read stream to abort.
130///
131/// This can happen when the "write" part aborts the stream.
132pub trait ReadAborted: maybe::Send {
133    /// An error that can occur while waiting for a stream to be aborted.
134    type Error: Error + maybe::Send + maybe::Sync + 'static;
135
136    /// Wait for a stream's corresponding write side to abort.
137    fn aborted(self) -> impl Future<Output = Result<ErrorCode, Self::Error>> + maybe::Send;
138}
139
140/// Finish the write stream.
141///
142/// Call when all data has been submitted and no further data will be written.
143pub trait Finish: maybe::Send {
144    /// An error that can occur while finishing the stream.
145    type Error: Error + maybe::Send + maybe::Sync + 'static;
146
147    /// Finish the stream.
148    fn finish(self) -> impl Future<Output = Result<(), Self::Error>> + maybe::Send;
149}
150
151/// Wait for the read stream to finish.
152///
153/// This can happen when the "write" part finishes the stream.
154pub trait Finished: maybe::Send {
155    /// An error that can occur while waiting for a stream to be aborted.
156    type Error: Error + ErrorAsErrorCode + maybe::Send + maybe::Sync + 'static;
157
158    /// Wait for a stream to finish.
159    fn finished(self) -> impl Future<Output = Result<(), Self::Error>> + maybe::Send;
160}
161
162/// An chunk of data with an explicit offset in the stream.
163#[derive(Debug)]
164pub struct Chunk<Data> {
165    /// The offset of the data in the stream.
166    pub offset: u64,
167    /// The data.
168    pub data: Data,
169}
170
171/// Read a [`Chunk`] from a stream.
172pub trait ReadChunk<ChunkType: ?Sized + ReadableChunk>: maybe::Send {
173    /// An error that can occur while reading a chunk from the stream.
174    type Error: Error + maybe::Send + maybe::Sync + 'static;
175
176    /// Read the data with the offset information from a stream.
177    fn read_chunk(
178        &mut self,
179        max_length: usize,
180        ordered: bool,
181    ) -> impl Future<
182        Output = Result<Option<Chunk<<ChunkType as ReadableChunk>::Data<'_>>>, Self::Error>,
183    > + maybe::Send;
184}
185
186/// Write a [`Chunk`] to a stream.
187pub trait WriteChunk<ChunkType: ?Sized + WriteableChunk>: maybe::Send {
188    /// An error that can occur while writing the chunk to a stream.
189    type Error: Error + maybe::Send + maybe::Sync + 'static;
190
191    /// Write the data with the offset information from a stream.
192    fn write_chunk<'a>(
193        &'a mut self,
194        buf: <ChunkType as WriteableChunk>::Data<'a>,
195    ) -> impl Future<Output = Result<(), Self::Error>> + 'a + maybe::Send;
196}
197
198/// Something that specifies the data type for a [`Chunk`] that can
199/// be read from a stream.
200pub trait ReadableChunk: maybe::Send {
201    /// The type that will hold the read data.
202    type Data<'a>: AsRef<[u8]>;
203}
204
205/// Something that specifies the data type for a [`Chunk`] that can
206/// be written to a stream.
207pub trait WriteableChunk: maybe::Send {
208    /// The type that will hold the data to write.
209    type Data<'a>: From<&'a [u8]>;
210}
211
212#[cfg(feature = "alloc")]
213pub mod chunk {
214    //! Provided [`ReadableChunk`] and [`WriteableChunk`] implementations.
215
216    use super::*;
217
218    /// A chunk type that represents operations that carry the data as [`u8`]
219    /// [`slice`]s or [`alloc::vec::Vec`]s
220    #[derive(Debug)]
221    pub struct U8;
222
223    impl WriteableChunk for U8 {
224        type Data<'b> = &'b [u8];
225    }
226
227    impl ReadableChunk for U8 {
228        type Data<'b> = alloc::vec::Vec<u8>;
229    }
230}