Skip to main content

http_type/stream/
impl.rs

1use super::*;
2
3/// Implementation of `From` trait for converting `usize` address into `&Stream`.
4impl From<usize> for &'static Stream {
5    /// Converts a memory address into a reference to `Stream`.
6    ///
7    /// # Arguments
8    ///
9    /// - `usize` - The memory address of the `Stream` instance.
10    ///
11    /// # Returns
12    ///
13    /// - `&'static Stream` - A reference to the `Stream` at the given address.
14    ///
15    /// # Safety
16    ///
17    /// - The address is guaranteed to be a valid `Stream` instance
18    ///   that was previously converted from a reference and is managed by the runtime.
19    #[inline(always)]
20    fn from(address: usize) -> &'static Stream {
21        unsafe { &*(address as *const Stream) }
22    }
23}
24
25/// Implementation of `From` trait for converting `usize` address into `&mut Stream`.
26impl<'a> From<usize> for &'a mut Stream {
27    /// Converts a memory address into a mutable reference to `Stream`.
28    ///
29    /// # Arguments
30    ///
31    /// - `usize` - The memory address of the `Stream` instance.
32    ///
33    /// # Returns
34    ///
35    /// - `&'a mut Stream` - A mutable reference to the `Stream` at the given address.
36    ///
37    /// # Safety
38    ///
39    /// - The address is guaranteed to be a valid `Stream` instance
40    ///   that was previously converted from a reference and is managed by the runtime.
41    #[inline(always)]
42    fn from(address: usize) -> &'a mut Stream {
43        unsafe { &mut *(address as *mut Stream) }
44    }
45}
46
47/// Implementation of `From` trait for converting `&Stream` into `usize` address.
48impl From<&Stream> for usize {
49    /// Converts a reference to `Stream` into its memory address.
50    ///
51    /// # Arguments
52    ///
53    /// - `&Stream` - The reference to the `Stream` instance.
54    ///
55    /// # Returns
56    ///
57    /// - `usize` - The memory address of the `Stream` instance.
58    #[inline(always)]
59    fn from(stream: &Stream) -> Self {
60        stream as *const Stream as usize
61    }
62}
63
64/// Implementation of `From` trait for converting `&mut Stream` into `usize` address.
65impl From<&mut Stream> for usize {
66    /// Converts a mutable reference to `Stream` into its memory address.
67    ///
68    /// # Arguments
69    ///
70    /// - `&mut Stream` - The mutable reference to the `Stream` instance.
71    ///
72    /// # Returns
73    ///
74    /// - `usize` - The memory address of the `Stream` instance.
75    #[inline(always)]
76    fn from(stream: &mut Stream) -> Self {
77        stream as *mut Stream as usize
78    }
79}
80
81/// Implementation of `AsRef` trait for `Stream`.
82impl AsRef<Stream> for Stream {
83    /// Converts `&Stream` to `&Stream` via memory address conversion.
84    ///
85    /// # Returns
86    ///
87    /// - `&Self` - A reference to the `Stream` instance.
88    #[inline(always)]
89    fn as_ref(&self) -> &Self {
90        let address: usize = self.into();
91        address.into()
92    }
93}
94
95/// Implementation of `AsMut` trait for `Stream`.
96impl AsMut<Stream> for Stream {
97    /// Converts `&mut Stream` to `&mut Stream` via memory address conversion.
98    ///
99    /// # Returns
100    ///
101    /// - `&mut Self` - A mutable reference to the `Stream` instance.
102    #[inline(always)]
103    fn as_mut(&mut self) -> &mut Self {
104        let address: usize = self.into();
105        address.into()
106    }
107}
108
109/// Implementation of `Lifetime` trait for `Stream`.
110impl Lifetime for Stream {
111    /// Converts a reference to the stream into a `'static` reference.
112    ///
113    /// # Returns
114    ///
115    /// - `&'static Self` - A reference to the stream with a `'static` lifetime.
116    ///
117    /// # Safety
118    ///
119    /// - The address is guaranteed to be a valid `Self` instance
120    ///   that was previously converted from a reference and is managed by the runtime.
121    #[inline(always)]
122    unsafe fn leak(&self) -> &'static Self {
123        let address: usize = self.into();
124        address.into()
125    }
126
127    /// Converts a reference to the stream into a `'static` mutable reference.
128    ///
129    /// # Returns
130    ///
131    /// - `&'static mut Self` - A mutable reference to the stream with a `'static` lifetime.
132    ///
133    /// # Safety
134    ///
135    /// - The address is guaranteed to be a valid `Self` instance
136    ///   that was previously converted from a reference and is managed by the runtime.
137    #[inline(always)]
138    unsafe fn leak_mut(&self) -> &'static mut Self {
139        let address: usize = self.into();
140        address.into()
141    }
142}
143
144/// Implementation of `Transport` trait for the plain TCP socket.
145///
146/// The socket is the reference transport: it already carries a socket
147/// identity, so its addresses are reported directly.
148impl Transport for TcpStream {
149    /// Reports the address of the remote end of the socket.
150    ///
151    /// # Returns
152    ///
153    /// - `Result<SocketAddr, io::Error>` - The peer address of the socket.
154    fn peer_addr(&self) -> Result<SocketAddr, io::Error> {
155        TcpStream::peer_addr(self)
156    }
157
158    /// Reports the address of the local end of the socket.
159    ///
160    /// # Returns
161    ///
162    /// - `Result<SocketAddr, io::Error>` - The local address of the socket.
163    fn local_addr(&self) -> Result<SocketAddr, io::Error> {
164        TcpStream::local_addr(self)
165    }
166}
167
168/// Implements [`Drop`] for [`PooledReader`].
169impl Drop for PooledReader<'_> {
170    /// Releases the buffer back to the pool for reuse by later requests.
171    fn drop(&mut self) {
172        let buffer: Vec<u8> = mem::take(self.get_mut_buffer());
173        return_read_buffer(buffer);
174    }
175}
176
177/// Implements non-blocking buffered reads for `PooledReader`.
178///
179/// Buffered bytes are served first; once drained, reads are delegated
180/// directly to the underlying stream.
181impl AsyncRead for PooledReader<'_> {
182    /// Polls to read data into the provided buffer.
183    ///
184    /// # Arguments
185    ///
186    /// - `Pin<&mut Self>` - The pinned reader.
187    /// - `&mut Context<'_>` - The task context.
188    /// - `&mut ReadBuf<'_>` - The destination buffer.
189    ///
190    /// # Returns
191    ///
192    /// - `Poll<io::Result<()>>` - Ready when data was read or an error occurred.
193    fn poll_read(
194        self: Pin<&mut Self>,
195        cx: &mut Context<'_>,
196        buf: &mut ReadBuf<'_>,
197    ) -> Poll<io::Result<()>> {
198        let this: &mut Self = self.get_mut();
199        if this.get_start() < this.get_end() {
200            let available: usize = this.get_end() - this.get_start();
201            let amount: usize = available.min(buf.remaining());
202            let end: usize = this.get_start() + amount;
203            buf.put_slice(&this.get_buffer()[this.get_start()..end]);
204            this.set_start(end);
205            return Poll::Ready(Ok(()));
206        }
207        Pin::new(&mut **this.get_mut_stream()).poll_read(cx, buf)
208    }
209}
210
211/// Implements buffered-read support for `PooledReader`.
212///
213/// The internal buffer is refilled from the stream only when fully
214/// consumed, so a single socket read serves multiple line parses.
215impl AsyncBufRead for PooledReader<'_> {
216    /// Polls to fill the internal buffer and returns the available data.
217    ///
218    /// # Arguments
219    ///
220    /// - `Pin<&mut Self>` - The pinned reader.
221    /// - `&mut Context<'_>` - The task context.
222    ///
223    /// # Returns
224    ///
225    /// - `Poll<io::Result<&[u8]>>` - Ready with the unconsumed bytes, or an error.
226    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
227        let this: &mut Self = self.get_mut();
228        let PooledReader {
229            stream,
230            buffer,
231            start,
232            end,
233        } = this;
234        if *start >= *end {
235            *start = 0;
236            *end = 0;
237            let mut read_buf: ReadBuf<'_> = ReadBuf::new(buffer);
238            match Pin::new(&mut **stream).poll_read(cx, &mut read_buf) {
239                Poll::Ready(Ok(())) => {
240                    *end = read_buf.filled().len();
241                }
242                Poll::Ready(Err(error)) => return Poll::Ready(Err(error)),
243                Poll::Pending => return Poll::Pending,
244            }
245        }
246        Poll::Ready(Ok(&buffer[*start..*end]))
247    }
248
249    /// Marks the given number of bytes as consumed.
250    ///
251    /// # Arguments
252    ///
253    /// - `Pin<&mut Self>` - The pinned reader.
254    /// - `usize` - The number of bytes to consume.
255    fn consume(self: Pin<&mut Self>, amount: usize) {
256        let this: &mut Self = self.get_mut();
257        let new_start: usize = (this.get_start() + amount).min(this.get_end());
258        this.set_start(new_start);
259    }
260}
261
262/// Inherent implementation of [`Stream`].
263impl Stream {
264    /// Boxes a transport into a `Stream` for the request pipeline.
265    ///
266    /// This is the single construction path: a plain TCP socket, a TLS session
267    /// and a per-request duplex stream all enter here, so nothing above the
268    /// transport line has to know which one it is serving. The transport is
269    /// type erased immediately, which keeps `Stream` a fixed size regardless of
270    /// the concrete protocol adapter behind it.
271    ///
272    /// # Arguments
273    ///
274    /// - `T` - The transport type to serve the request cycle over.
275    /// - `RequestConfig` - The parsing limits and read timeout for the cycle.
276    /// - `bool` - Whether the connection starts already closed.
277    ///
278    /// # Returns
279    ///
280    /// - `Self` - A stream serving bytes through the boxed transport.
281    pub fn from_transport<T>(transport: T, request_config: RequestConfig, closed: bool) -> Self
282    where
283        T: Transport + 'static,
284    {
285        Self {
286            stream: Box::new(transport),
287            request_config,
288            closed,
289            leftover: Vec::new(),
290            leftover_start: 0,
291            leftover_end: 0,
292            line_buffer: String::with_capacity(REQUEST_LINE_BUFFER_CAPACITY),
293            header_line_buffer: String::with_capacity(HEADER_LINE_BUFFER_CAPACITY),
294        }
295    }
296
297    /// Boxes a TCP socket into a `Stream` for the request pipeline.
298    ///
299    /// Kept as the socket-facing constructor so the accept loop keeps its
300    /// existing call shape; it delegates to `from_transport`, so there is one
301    /// construction path rather than two.
302    ///
303    /// # Arguments
304    ///
305    /// - `TcpStream` - The accepted socket to serve the request cycle over.
306    /// - `RequestConfig` - The parsing limits and read timeout for the cycle.
307    /// - `bool` - Whether the connection starts already closed.
308    ///
309    /// # Returns
310    ///
311    /// - `Self` - A stream serving bytes through the boxed socket.
312    pub fn new(stream: TcpStream, request_config: RequestConfig, closed: bool) -> Self {
313        Self::from_transport(stream, request_config, closed)
314    }
315
316    /// Reports the address of the remote end of the transport.
317    ///
318    /// Delegates to the transport itself, so a transport without a socket
319    /// identity answers with an error rather than a fabricated address.
320    ///
321    /// # Returns
322    ///
323    /// - `Result<SocketAddr, io::Error>` - The peer address reported by the transport.
324    #[inline(always)]
325    pub fn get_peer_addr(&self) -> Result<SocketAddr, io::Error> {
326        self.get_stream().peer_addr()
327    }
328
329    /// Reports the address of the local end of the transport.
330    ///
331    /// Delegates to the transport itself, so a transport without a socket
332    /// identity answers with an error rather than a fabricated address.
333    ///
334    /// # Returns
335    ///
336    /// - `Result<SocketAddr, io::Error>` - The local address reported by the transport.
337    #[inline(always)]
338    pub fn get_local_addr(&self) -> Result<SocketAddr, io::Error> {
339        self.get_stream().local_addr()
340    }
341
342    /// Checks if the connection should be kept alive.
343    ///
344    /// This method evaluates whether the connection should remain open based on
345    /// the closed state and the keep_alive parameter.
346    ///
347    /// # Arguments
348    ///
349    /// - `bool` - Whether keep-alive is enabled for the request.
350    ///
351    /// # Returns
352    ///
353    /// - `bool` - True if the connection should be kept alive, otherwise false.
354    #[inline(always)]
355    pub fn is_keep_alive(&self, keep_alive: bool) -> bool {
356        !self.get_closed() && keep_alive
357    }
358
359    /// Parses the HTTP request content from the stream into the given request.
360    ///
361    /// The request is reset first, then filled in place so its existing
362    /// allocations are reused across keep-alive requests.
363    ///
364    /// # Arguments
365    ///
366    /// - `&mut Request` - The request object to fill.
367    ///
368    /// # Returns
369    ///
370    /// - `Result<(), RequestError>` - Ok on success, or an error if parsing fails.
371    async fn fill_http_from_stream(&mut self, request: &mut Request) -> Result<(), RequestError> {
372        request.reset();
373        let config: RequestConfig = *self.get_request_config();
374        let buffer_size: usize = config.get_buffer_size();
375        let max_path_size: usize = config.get_max_path_size();
376        // Take any bytes the previous request read ahead, BEFORE borrowing the
377        // socket: those bytes already left the socket and cannot be re-read, so
378        // dropping them would silently discard a pipelined request.
379        let seeded: Vec<u8> = {
380            let start: usize = self.get_leftover_start();
381            let end: usize = self.get_leftover_end();
382            let mut pending: Vec<u8> = Vec::new();
383            if start < end {
384                let leftover: Vec<u8> = mem::take(self.get_mut_leftover());
385                let take: usize = (end - start).min(leftover.len());
386                pending.extend_from_slice(&leftover[start..start + take]);
387            }
388            self.set_leftover(Vec::new());
389            self.set_leftover_start(0);
390            self.set_leftover_end(0);
391            pending
392        };
393        let buffer: Vec<u8> = take_read_buffer(buffer_size);
394        // Split the borrow of the stream: the reader takes the transport, the
395        // line buffers are separate fields, so both can be held at once.
396        let Stream {
397            stream,
398            line_buffer,
399            header_line_buffer,
400            ..
401        } = self;
402        let mut reader: PooledReader<'_> = PooledReader::new(stream, buffer);
403        if !seeded.is_empty() {
404            let target: &mut Vec<u8> = reader.get_mut_buffer();
405            let copy_len: usize = seeded.len().min(target.len());
406            target[..copy_len].copy_from_slice(&seeded[..copy_len]);
407            reader.set_end(copy_len);
408        }
409        line_buffer.clear();
410        AsyncBufReadExt::read_line(&mut reader, line_buffer).await?;
411        let (method, path, version): (RequestMethod, &str, RequestVersion) =
412            Request::get_http_first_line(line_buffer)?;
413        Request::check_http_path_size(path, max_path_size)?;
414        let hash_index: Option<usize> = path.find(HASH);
415        let query_index: Option<usize> = path.find(QUERY);
416        let query: &str = Request::get_http_query(path, query_index, hash_index);
417        Request::fill_http_querys(query, request.get_mut_querys());
418        let path_slice: &str = Request::get_http_path(path, query_index, hash_index);
419        request.get_mut_path().push_str(path_slice);
420        let content_size: usize = request
421            .get_http_headers(&mut reader, &config, header_line_buffer)
422            .await?;
423        request.set_method(method);
424        request.set_version(version);
425        Request::fill_http_body(&mut reader, request.get_mut_body(), content_size).await?;
426        // Preserve bytes read ahead for the next pipelined request: they have
427        // already left the socket and cannot be read again.
428        let reader_start: usize = reader.get_start();
429        let reader_end: usize = reader.get_end();
430        let pending: Vec<u8> = if reader_start < reader_end {
431            reader.get_buffer()[reader_start..reader_end].to_vec()
432        } else {
433            Vec::new()
434        };
435        drop(reader);
436        let pending_len: usize = pending.len();
437        self.set_leftover(pending);
438        self.set_leftover_start(0);
439        self.set_leftover_end(pending_len);
440        Ok(())
441    }
442
443    /// Parses an HTTP request from a TCP stream into the given request.
444    ///
445    /// The request is reset and filled in place, reusing its allocations.
446    /// If the timeout is DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS, no timeout is applied.
447    ///
448    /// # Arguments
449    ///
450    /// - `&mut Request` - The request object to reset and fill.
451    ///
452    /// # Returns
453    ///
454    /// - `Result<(), RequestError>` - Ok on success, or an error if parsing fails.
455    pub async fn try_fill_http_request(
456        &mut self,
457        request: &mut Request,
458    ) -> Result<(), RequestError> {
459        if self.get_closed() {
460            return Err(RequestError::ServerClosedConnection(HttpStatus::BadRequest));
461        }
462        let timeout_ms: u64 = self.get_request_config().get_read_timeout_ms();
463        if timeout_ms == DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS {
464            return self.fill_http_from_stream(request).await;
465        }
466        let duration: Duration = Duration::from_millis(timeout_ms);
467        let mut reading: Pin<&mut _> = pin!(self.fill_http_from_stream(request));
468        // A request whose bytes have already arrived is read on the first
469        // poll, so the ordinary case never arms a timer at all. Arming one
470        // costs a timer registration and a cancellation per request, and that
471        // churn is the most expensive thing a request path can do once the
472        // concurrency is high enough for the timer driver to become a
473        // bottleneck. The timer is armed only when the read really has to
474        // wait, which is exactly when the timeout can still fire.
475        if let Some(result) = poll_once(reading.as_mut()).await {
476            return result;
477        }
478        timeout(duration, reading).await?
479    }
480
481    /// Parses an HTTP request from a TCP stream.
482    ///
483    /// Wraps the stream in a buffered reader and delegates to `http_from_reader`.
484    /// If the timeout is DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS, no timeout is applied.
485    ///
486    /// # Returns
487    ///
488    /// - `Result<Request, RequestError>` - The parsed request or an error.
489    pub async fn try_get_http_request(&mut self) -> Result<Request, RequestError> {
490        let mut request: Request = Request::default();
491        self.try_fill_http_request(&mut request).await?;
492        Ok(request)
493    }
494
495    /// Parses a WebSocket request from a TCP stream.
496    ///
497    /// Wraps the stream in a buffered reader and delegates to `ws_from_reader`.
498    /// If the timeout is DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS, no timeout is applied.
499    ///
500    /// # Returns
501    ///
502    /// - `Result<RequestBody, RequestError>` - The parsed WebSocket request or an error.
503    pub async fn try_get_websocket_request(&mut self) -> Result<RequestBody, RequestError> {
504        if self.get_closed() {
505            return Err(RequestError::ServerClosedConnection(HttpStatus::BadRequest));
506        }
507        let config: RequestConfig = *self.get_request_config();
508        let buffer_size: usize = config.get_buffer_size();
509        let read_timeout_ms: u64 = config.get_read_timeout_ms();
510        let mut dynamic_buffer: Vec<u8> = Vec::with_capacity(buffer_size);
511        let mut temp_buffer: Vec<u8> = vec![0; buffer_size];
512        let mut full_frame: Vec<u8> = Vec::new();
513        let mut is_client_response: bool = false;
514        let duration_opt: Option<Duration> =
515            if read_timeout_ms == DEFAULT_LOW_SECURITY_READ_TIMEOUT_MS {
516                None
517            } else {
518                let adjusted_timeout_ms: u64 = (read_timeout_ms >> 1) + (read_timeout_ms & 1);
519                Some(Duration::from_millis(adjusted_timeout_ms))
520            };
521        loop {
522            let len: usize = match self
523                .get_websocket_from_stream(&mut temp_buffer, duration_opt, &mut is_client_response)
524                .await
525            {
526                Ok(Some(len)) => len,
527                Ok(None) => continue,
528                Err(error) => return Err(error),
529            };
530            if len == 0 {
531                return Err(RequestError::IncompleteWebSocketFrame(
532                    HttpStatus::BadRequest,
533                ));
534            }
535            dynamic_buffer.extend_from_slice(&temp_buffer[..len]);
536            while let Some((frame, consumed)) = WebSocketFrame::decode_ws_frame(&dynamic_buffer) {
537                is_client_response = true;
538                dynamic_buffer.drain(0..consumed);
539                match frame.get_opcode() {
540                    WebSocketOpcode::Close => {
541                        return Err(RequestError::ClientClosedConnection(HttpStatus::BadRequest));
542                    }
543                    WebSocketOpcode::Ping | WebSocketOpcode::Pong => continue,
544                    WebSocketOpcode::Text | WebSocketOpcode::Binary => {
545                        match frame.build_full_frame(&mut full_frame) {
546                            Ok(Some(result)) => return Ok(result),
547                            Ok(None) => continue,
548                            Err(error) => return Err(error),
549                        }
550                    }
551                    _ => {
552                        return Err(RequestError::WebSocketOpcodeUnsupported(
553                            HttpStatus::NotImplemented,
554                        ));
555                    }
556                }
557            }
558        }
559    }
560
561    /// Reads data from the stream with optional timeout handling.
562    ///
563    /// # Arguments
564    ///
565    /// - `&mut [u8]` - The buffer to read data into.
566    /// - `Option<Duration>` - The optional timeout duration. If Some, timeout is applied; if None, no timeout.
567    /// - `&mut bool` - Mutable reference to track if we got a client response.
568    ///
569    /// # Returns
570    ///
571    /// - `Result<Option<usize>, RequestError>` - The number of bytes read, None for timeout/ping, or an error.
572    pub(crate) async fn get_websocket_from_stream(
573        &mut self,
574        buffer: &mut [u8],
575        duration_opt: Option<Duration>,
576        is_client_response: &mut bool,
577    ) -> Result<Option<usize>, RequestError> {
578        let stream: &mut Box<dyn Transport> = self.get_mut_stream();
579        if let Some(duration) = duration_opt {
580            return match timeout(duration, stream.read(buffer)).await {
581                Ok(result) => match result {
582                    Ok(len) => Ok(Some(len)),
583                    Err(error) => Err(error.into()),
584                },
585                Err(error) => {
586                    if !*is_client_response {
587                        return Err(error.into());
588                    }
589                    *is_client_response = false;
590                    self.try_send(&PING_FRAME).await?;
591                    Ok(None)
592                }
593            };
594        }
595        match stream.read(buffer).await {
596            Ok(len) => Ok(Some(len)),
597            Err(error) => Err(error.into()),
598        }
599    }
600
601    /// Sends data over the stream.
602    ///
603    /// # Arguments
604    ///
605    /// - `D` - The data to send, which must implement `AsRef<[u8]>`.
606    ///
607    /// # Returns
608    ///
609    /// - `Result<(), ResponseError>` - Result indicating success or failure.
610    pub async fn try_send<D>(&mut self, data: D) -> Result<(), ResponseError>
611    where
612        D: AsRef<[u8]>,
613    {
614        if self.get_closed() {
615            return Err(ResponseError::ConnectionClosed);
616        }
617        Ok(self.get_mut_stream().write_all(data.as_ref()).await?)
618    }
619
620    /// Sends data over the stream.
621    ///
622    /// # Arguments
623    ///
624    /// - `D` - The data to send, which must implement `AsRef<[u8]>`.
625    ///
626    /// # Panics
627    ///
628    /// Panics if the write operation fails.
629    pub async fn send<D>(&mut self, data: D)
630    where
631        D: AsRef<[u8]>,
632    {
633        self.try_send(data).await.unwrap();
634    }
635
636    /// Sends multiple data.
637    ///
638    /// # Arguments
639    ///
640    /// - `I` - The data list to send, which must implement `IntoIterator<Item = D>` with
641    ///   `D` requiring the `AsRef<[u8]>` bound.
642    ///
643    /// # Returns
644    ///
645    /// - `Result<(), ResponseError>` - Result indicating success or failure.
646    pub async fn try_send_list<I, D>(&mut self, data_iter: I) -> Result<(), ResponseError>
647    where
648        I: IntoIterator<Item = D>,
649        D: AsRef<[u8]>,
650    {
651        if self.get_closed() {
652            return Err(ResponseError::ConnectionClosed);
653        }
654        let stream: &mut Box<dyn Transport> = self.get_mut_stream();
655        for data in data_iter {
656            stream.write_all(data.as_ref()).await?;
657        }
658        Ok(())
659    }
660
661    /// Sends multiple data.
662    ///
663    /// # Arguments
664    ///
665    /// - `I` - The data list to send, which must implement `IntoIterator<Item = D>` with
666    ///   `D` requiring the `AsRef<[u8]>` bound.
667    ///
668    /// # Panics
669    ///
670    /// Panics if any write operation fails.
671    pub async fn send_list<I, D>(&mut self, data_iter: I)
672    where
673        I: IntoIterator<Item = D>,
674        D: AsRef<[u8]>,
675    {
676        self.try_send_list(data_iter).await.unwrap();
677    }
678
679    /// Flushes all buffered data to the stream.
680    ///
681    /// # Returns
682    ///
683    /// - `Result<(), ResponseError>` - Result indicating success or failure.
684    pub async fn try_flush(&mut self) -> Result<(), ResponseError> {
685        if self.get_closed() {
686            return Err(ResponseError::ConnectionClosed);
687        }
688        Ok(self.get_mut_stream().flush().await?)
689    }
690
691    /// Flushes all buffered data to the stream.
692    ///
693    /// # Panics
694    ///
695    /// Panics if the flush operation fails.
696    pub async fn flush(&mut self) {
697        self.try_flush().await.unwrap();
698    }
699}