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}