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 to abort.
126    fn aborted(self) -> impl Future<Output = Result<ErrorCode, Self::Error>> + maybe::Send;
127}
128
129/// Finish the write stream.
130///
131/// Call when all data has been submitted and no further data will be written.
132pub trait Finish: maybe::Send {
133    /// An error that can occur while finishing the stream.
134    type Error: Error + maybe::Send + maybe::Sync + 'static;
135
136    /// Finish the stream.
137    fn finish(self) -> impl Future<Output = Result<(), Self::Error>> + maybe::Send;
138}
139
140/// An chunk of data with an explicit offset in the stream.
141#[derive(Debug)]
142pub struct Chunk<Data> {
143    /// The offset of the data in the stream.
144    pub offset: u64,
145    /// The data.
146    pub data: Data,
147}
148
149/// Read a [`Chunk`] from a stream.
150pub trait ReadChunk<ChunkType: ?Sized + ReadableChunk>: maybe::Send {
151    /// An error that can occur while reading a chunk from the stream.
152    type Error: Error + maybe::Send + maybe::Sync + 'static;
153
154    /// Read the data with the offset information from a stream.
155    fn read_chunk(
156        &mut self,
157        max_length: usize,
158        ordered: bool,
159    ) -> impl Future<
160        Output = Result<Option<Chunk<<ChunkType as ReadableChunk>::Data<'_>>>, Self::Error>,
161    > + maybe::Send;
162}
163
164/// Write a [`Chunk`] to a stream.
165pub trait WriteChunk<ChunkType: ?Sized + WriteableChunk>: maybe::Send {
166    /// An error that can occur while writing the chunk to a stream.
167    type Error: Error + maybe::Send + maybe::Sync + 'static;
168
169    /// Write the data with the offset information from a stream.
170    fn write_chunk<'a>(
171        &'a mut self,
172        buf: <ChunkType as WriteableChunk>::Data<'a>,
173    ) -> impl Future<Output = Result<(), Self::Error>> + 'a + maybe::Send;
174}
175
176/// Something that specifies the data type for a [`Chunk`] that can
177/// be read from a stream.
178pub trait ReadableChunk: maybe::Send {
179    /// The type that will hold the read data.
180    type Data<'a>: AsRef<[u8]>;
181}
182
183/// Something that specifies the data type for a [`Chunk`] that can
184/// be written to a stream.
185pub trait WriteableChunk: maybe::Send {
186    /// The type that will hold the data to write.
187    type Data<'a>: From<&'a [u8]>;
188}
189
190#[cfg(feature = "alloc")]
191pub mod chunk {
192    //! Provided [`ReadableChunk`] and [`WriteableChunk`] implementations.
193
194    use super::*;
195
196    /// A chunk type that represents operations that carry the data as [`u8`]
197    /// [`slice`]s or [`alloc::vec::Vec`]s
198    #[derive(Debug)]
199    pub struct U8;
200
201    impl WriteableChunk for U8 {
202        type Data<'b> = &'b [u8];
203    }
204
205    impl ReadableChunk for U8 {
206        type Data<'b> = alloc::vec::Vec<u8>;
207    }
208}