Skip to main content

vibeio_http/
incoming.rs

1use std::{
2    pin::Pin,
3    task::{Context, Poll},
4};
5
6use http_body::Body;
7
8#[cfg(feature = "h2")]
9use crate::H2Body;
10#[cfg(feature = "h1")]
11use crate::Http1Body;
12
13/// An incoming HTTP request body.
14///
15/// `Incoming` is the concrete body type placed inside every
16/// [`Request`](http::Request) passed to the user-supplied handler.
17///
18/// Data frames are yielded as [`bytes::Bytes`] chunks. Trailer frames (like
19/// HTTP/1.1 chunked trailers) are forwarded transparently. The stream ends when
20/// [`Body::poll_frame`] returns `Poll::Ready(None)`.
21#[allow(private_interfaces)]
22pub enum Incoming {
23    #[cfg(feature = "h1")]
24    H1(Http1Body),
25    #[cfg(feature = "h2")]
26    H2(H2Body),
27    #[cfg(feature = "h3")]
28    Boxed(Pin<Box<dyn Body<Data = bytes::Bytes, Error = std::io::Error> + Send + Sync>>),
29    #[cfg(any(feature = "h2", feature = "h3"))]
30    Empty,
31}
32
33impl Body for Incoming {
34    type Data = bytes::Bytes;
35    type Error = std::io::Error;
36
37    #[inline]
38    fn poll_frame(
39        self: Pin<&mut Self>,
40        cx: &mut Context<'_>,
41    ) -> Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
42        match self.get_mut() {
43            #[cfg(feature = "h1")]
44            Self::H1(ref mut inner) => Pin::new(inner).poll_frame(cx),
45            #[cfg(feature = "h2")]
46            Self::H2(ref mut inner) => Pin::new(inner).poll_frame(cx),
47            #[cfg(feature = "h3")]
48            Self::Boxed(inner) => inner.as_mut().poll_frame(cx),
49            #[cfg(any(feature = "h2", feature = "h3"))]
50            Self::Empty => Poll::Ready(None),
51        }
52    }
53
54    #[inline]
55    fn is_end_stream(&self) -> bool {
56        match self {
57            #[cfg(feature = "h1")]
58            Self::H1(inner) => inner.is_end_stream(),
59            #[cfg(feature = "h2")]
60            Self::H2(inner) => inner.is_end_stream(),
61            #[cfg(feature = "h3")]
62            Self::Boxed(inner) => inner.is_end_stream(),
63            #[cfg(any(feature = "h2", feature = "h3"))]
64            Self::Empty => true,
65        }
66    }
67
68    #[inline]
69    fn size_hint(&self) -> http_body::SizeHint {
70        match self {
71            #[cfg(feature = "h1")]
72            Self::H1(inner) => inner.size_hint(),
73            #[cfg(feature = "h2")]
74            Self::H2(inner) => inner.size_hint(),
75            #[cfg(feature = "h3")]
76            Self::Boxed(inner) => inner.size_hint(),
77            #[cfg(any(feature = "h2", feature = "h3"))]
78            Self::Empty => http_body::SizeHint::default(),
79        }
80    }
81}