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}